赋值规则

假设我们要把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>