I'm using the code in func Root
as a guide to create another method Login
shown below. In particular, in Root
, I assign the literal Book{}
to b
and then use the result in the Scan
. That code doesn't throw any errors (although I'm not sure if it's nice code), but when I try to do something similar in the Login
function, which I'm modifying from this blogpost, I get this error
cannot use User literal (type User) as type *User in assignment
for what it's worth, I also get this error right above when I compile
no new variables on left side of :=
but aren't I doing the same thing in the second method, namely assigning the literal u := User{}
to a variable and then using it in the scan?
Can you explain using the code below when you can and can't use a literal for type in an assignment?
func Root(w http.ResponseWriter, r *http.Request) {
rows, err := db.Query("SELECT title, author, description FROM books")
books := []Book{}
for rows.Next() {
b := Book{}
err := rows.Scan(&b.Title, &b.Author, &b.Description)
PanicIf(err)
books = append(books, b)
}
...//code ommitted
func Login(password, email string) (u *User, err error) {
u := User{}
db.QueryRow("select * from users where email=$1 ", email).Scan(&u.Id, &u.Password, &u.Email)
if err != nil {
return
}
err = bcrypt.CompareHashAndPassword(u.Password, []byte(password))
if err != nil {
u = nil
}
return
}
Simplifying your example to focus on the essentials:
package main
import "net/http"
type Book struct{}
type User struct{}
func Root(w http.ResponseWriter, r *http.Request) {
books := []Book{}
_ = books
}
func Login(password, email string) (u *User, err error) {
// no new variables on left side of :=
// cannot use User literal (type User) as type *User in assignment
// u := User{}
u = &User{}
return
}
func main() {}
The function declaration for Login
declares a result parameter u *User
, a pointer to type User
.
The u := User{}
statement is a short variable declaration of type User
.
The Go Programming Language Specification
A short variable declaration uses the syntax:
ShortVarDecl = IdentifierList ":=" ExpressionList .
It is shorthand for a regular variable declaration with initializer expressions but no types:
"var" IdentifierList = ExpressionList .
Unlike regular variable declarations, a short variable declaration may redeclare variables provided they were originally declared earlier in the same block with the same type, and at least one of the non-blank variables is new. As a consequence, redeclaration can only appear in a multi-variable short declaration. Redeclaration does not introduce a new variable; it just assigns a new value to the original.
Since the variable u
has already been declared in the same block (u *User
), the compiler complains that u := User{}
has "no new variables on left side of :=
." Write u = User{}
for a simple assignment.
The statement books := []Book{}
is a short variable declaration for a new variable, book
, in the block.
The declaration u *User
says that u
is a pointer to a variable of type User
.
The Go Programming Language Specification
Composite literals construct values for structs, arrays, slices, and maps and create a new value each time they are evaluated. They consist of the type of the value followed by a brace-bound list of composite elements. An element may be a single expression or a key-value pair.
The LiteralType must be a struct, array, slice, or map type (the grammar enforces this constraint except when the type is given as a TypeName). The types of the expressions must be assignable to the respective field, element, and key types of the LiteralType; there is no additional conversion.
Taking the address of a composite literal generates a pointer to a unique instance of the literal's value.
The composite literal User{}
is a literal value of type User
, not *User
. The compiler complains that "cannot use User literal (type User) as type *User in assignment
." Take the address of the composite literal for a pointer to a literal value of type User
(*User
). Write u = &User{}
.
b := Book{}
defines a new variable (b
wasn't defined before), so it can take the value type Book
u := User{}
doesn't define a new variable, because it was part of the method return parameter u *User
, so you can't use :=
.u=&User{}
.u
here is a named result parameter:
if the function executes a return statement with no arguments, the current values of the result parameters are used as the returned values.