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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With