赋值规则
假设我们要把right赋值给left
left = right
left与right需满足以下规则之一:
(1)双方类型相同
(2)双方有相同的底层类型,且至少有一个是未命名类型。
(3)left是接口类型,right是具体类型,right的方法集是left的超集。
(4)right是nil,left是pointer、function、slice、map、channel、interface。
类型相同,例子(1/2):
package main
import (
"github.com/davecgh/go-spew/spew"
)
func main() {
var left int
var right int
// 可以赋值
// 双方均为int类型
left, right = 1, 2
left = right
spew.Dump(left, right)
}
输出
(int) 2
(int) 2
类型相同,例子(2/2):
package main
import (
"github.com/davecgh/go-spew/spew"
)
type Person struct {
Name string
}
func main() {
var left Person
var right Person
left = Person{
Name: "xiaoYi1",
}
right = Person{
Name: "xiaoYi2",
}
// 可以赋值
// 双方均为自定义类型Person
left = right
spew.Dump(left, right)
}
输出
(main.Person) {
Name: (string) (len=7) "xiaoYi2"
}
(main.Person) {
Name: (string) (len=7) "xiaoYi2"
}
类型不同,但底层类型相同,且至少有一个未命名类型,例子:
package main
import (
"github.com/davecgh/go-spew/spew"
)
type Left chan int
type Right Left
func main() {
var left Left
// 可以赋值
// left是命名类型
// make(chan int) 是类型字面量
// 左右双方底层类型均是chan int
left = make(chan int, 1)
// 不可以赋值
var right Right
right = make(chan int, 1)
// Cannot use 'right' (type Right) as the type Left
// left = right // 类型不同无法赋值,且没有一个是未命名类型
// 不可以赋值
// Cannot use 'new(chan int)' (type *chan int) as the type Left
// left = new(chan int) // new(chan int)返回*chan int,双方底层类型不同无法赋值
spew.Dump(left, right)
}
left是接口类型,right是具体类型,例子:
package main
import (
"fmt"
"github.com/davecgh/go-spew/spew"
)
type Man interface{
Say()
}
type People struct {
Name string
}
func (p People) Say() {
fmt.Println("我是", p.Name)
}
func main() {
var left Man
xiaoYi := People{
Name: "xiaoYi",
}
// 可以赋值
// xiaoYi是具体类型
// xiaoYi的方法集是Man的超集
// 超集:大于等于
left = xiaoYi
spew.Dump(left)
}
输出
(main.People) {
Name: (string) (len=6) "xiaoYi"
}
right是nil,例子:
package main
import "github.com/davecgh/go-spew/spew"
func main() {
// 可以赋值
// 管道
var a chan int
a = nil
// 可以赋值
// 切片
var b []int
b = nil
// 可以赋值
// map
var c [] map[string]string
c = nil
// 可以赋值
// 指针
var d *int
d = nil
// 可以赋值
// 方法
type E func() int
var e E
e = nil
// 可以赋值
// 接口
var f interface{}
f = nil
spew.Dump(a, b, c, d, e, f)
}
输出
(chan int) <nil>
([]int) <nil>
([]map[string]string) <nil>
(*int)(<nil>)
(main.E) <nil>
(interface {}) <nil>