Use a literal for type input

I am using the code in func Root

as a guide to create another method Login

shown below. Specifically, in Root

I assign to a literal Book{}

b

and then use the result in Scan

. This code does not throw any errors (although I'm not sure if this is good code), but when I try to do something like this in a function Login

that I am 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 don't I do the same in the second method, namely by assigning the variable a letter u := User{}

and then using it in the scan?

Can you explain using the code below when you can and cannot use a literal for a 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
}

      

+3


source to share


2 answers


Simplifying your example to focus on the basics:

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() {}

      

A function declaration for Login

declares a result parameter u *User

, a pointer to a type User

.

An operator u := User{}

is a short type variable declaration User

.

Go Programming Language Specification

Short statement variable

A short variable declaration uses the syntax:

ShortVarDecl = IdentifierList ": =" ExpressionList.

This is shorthand for declaring a regular variable with an expression initializer, but not types:

"var" IdentifierList = ExpressionList.

Unlike regular variable declarations, declaring a short variable can override variables if they were originally declared earlier in the same block with the same type and at least one of the non-empty variables is new. As a consequence, re-styling can only appear in a short declaration with multiple variables. The Redeclaration does not introduce a new variable; it just assigns a new value to the original.



Since the variable is u

already declared in the same ( u *User

) block , the compiler complains that it u := User{}

has " no new variables on left side of :=

". Write u = User{}

for a simple appointment.

A statement books := []Book{}

is a short variable declaration for a new variable book

in a block.

The declaration u *User

states that it u

is a pointer to a variable of the type User

.

Go Programming Language Specification

Composite literals

Composite literals build values ​​for structures, arrays, slices, and maps, and create a new value each time they are evaluated. They consist of a value type followed by a parenthesized list of constituent elements. The element can be a single expression or a key-value pair.

LiteralType must be a structure, array, slice, or map type (the grammar enforces this restriction, unless the type is specified as TypeName). Expression types must be assigned to the appropriate field, element, and LiteralType key types; There is no additional conversion.

Taking the address of a compound literal creates a pointer to a unique instance of the literal value.

A compound literal User{}

is a literal type value User

, not a *User

. The compiler complains that " cannot use User literal (type User) as type *User in assignment

". Take the address of a compound literal for a pointer to a literal value of type User

( *User

). Write u = &User{}

.

+3


source


  • b := Book{}

    defines a new variable ( b

    not previously defined), so it can take on a value typeBook

  • u := User{}

    doesn't define a new variable since it was part of the return parameter of the method u *User

    , so you can't use :=

    .
    It will be u=&User{}

    .

u

here's the named result parameter :



if the function executes a return statement with no arguments, the current values ​​of the result parameters are used as return values.

+1


source







All Articles