我使用func Root
中的代码作为指南来创建下面显示的另一种方法Login
。特别是,在Root
中,我将文字Book{}
分配给b
,然后使用Scan
中的结果。该代码不会抛出任何错误(虽然我不确定它是否是一个很好的代码),但是当我尝试在Login
函数中执行类似的操作时,我会这样做; m从此blogpost修改,我收到此错误
cannot use User literal (type User) as type *User in assignment
为了它的价值,我在编译时也会出现这个错误
no new variables on left side of :=
但是我没有在第二种方法中做同样的事情,即将文字u := User{}
分配给变量然后在扫描中使用它?
您是否可以在可以的情况下使用以下代码进行解释,并且无法在作业中使用文字作为类型?
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
}
答案 0 :(得分:6)
简化您的示例以专注于要点:
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() {}
Login
的函数声明声明了一个结果参数u *User
,一个指向User
类型的指针。
u := User{}
语句是类型为User
的简短变量声明。
The Go Programming Language Specification
短变量声明使用语法:
ShortVarDecl = IdentifierList":=" ExpressionList。
它是带初始化程序的常规变量声明的简写 表达式,但没有类型:
"无功" IdentifierList = ExpressionList。
与常规变量声明不同,短变量声明可以 重新声明变量,只要它们最初是在早些时候宣布的 具有相同类型的相同块,以及至少一个非空白块 变量是新的。因此,重新声明只能出现在 多变量简短声明。重新申报不会引入 新变量;它只是为原始版本赋予了一个新值。
由于变量u
已在同一个块(u *User
)中声明,因此编译器会抱怨u := User{}
有" no new variables on left side of :=
。&#34 ;写u = User{}
进行简单的作业。
语句books := []Book{}
是块中新变量book
的简短变量声明。
声明u *User
表示u
是指向User
类型变量的指针。
The Go Programming Language Specification
复合文字构造结构,数组,切片和的值 映射并在每次评估时创建新值。他们包括 值的类型后跟一个大括号括号的复合列表 元素。元素可以是单个表达式或键值对。
LiteralType必须是结构,数组,切片或地图类型( 语法强制执行此约束,除非将类型指定为a 类型名)。表达式的类型必须可分配给 LiteralType的相应字段,元素和键类型;有 没有额外的转换。
获取复合文字的地址会生成指向a的指针 文字值的唯一实例。
复合文字User{}
是User
类型的文字值,而不是*User
。编译器抱怨" cannot use User literal (type User) as type *User in assignment
。"将复合文字的地址作为指向类型User
(*User
)的文字值的指针。写u = &User{}
。
答案 1 :(得分:2)
b := Book{}
定义了一个新变量(b
之前未定义过),因此可以采用值类型Book
u := User{}
没有定义新变量,因为它是方法返回参数u *User
的一部分,因此您无法使用:=
。u=&User{}
。如果函数执行不带参数的return语句,则结果参数的当前值将用作返回值。