Slide 1

Slide 1 text

Assignability Assignability Go Go 18 March 2021 18 March 2021 yyh-gl yyh-gl

Slide 2

Slide 2 text

2 2

Slide 3

Slide 3 text

yyh-gl Honda, Yusuke yyh-gl Honda, Yusuke DMM.com Go DMM.com Go Go Go The Go Programming Language Specification The Go Programming Language Specification (https://yyh-gl.github.io/tech-blog/blog/uncredible-codes-from-go-spec/) (https://yyh-gl.github.io/tech-blog/blog/uncredible-codes-from-go-spec/) Twitter: @yyh_gl Twitter: @yyh_gl (https://twitter.com/yyh_gl) (https://twitter.com/yyh_gl) 3 3

Slide 4

Slide 4 text

Go Assignability Go Assignability 1. Assignability 1. Assignability 2. Assignable 2. Assignable 3. 3. Go Assignability Go Assignability (https://golang.org/ref/spec#Assignability) (https://golang.org/ref/spec#Assignability) 4 4

Slide 5

Slide 5 text

Assignability Assignability 5 5

Slide 6

Slide 6 text

Assignability = Assignability = Go 6 Go 6 6 6

Slide 7

Slide 7 text

Assignable Assignable 7 7

Slide 8

Slide 8 text

Assignable Assignable x 6 x 6 x T Assignable x T Assignable 8 8

Slide 9

Slide 9 text

1 1 x T identical x T identical identical syumai identical syumai (hoge) (hoge) package main package main import "fmt" import "fmt" func main() { func main() { var x int = 1 var x int = 1 var t1 int = x // t1およびxの型はint var t1 int = x // t1およびxの型はint fmt.Println(t1) // 1 fmt.Println(t1) // 1 var y string = "yyy" var y string = "yyy" var t2 int = y // t2とyの型が異なるのでエラー var t2 int = y // t2とyの型が異なるのでエラー } } Run 9 9

Slide 10

Slide 10 text

2 2 T x V underlying type T x V underlying type && T V defined type && T V defined type package main package main import "fmt" import "fmt" const one int = 1 const one int = 1 type ( type ( T1 struct{ number int } // T1のunderlying typeはstruct{ number int } T1 struct{ number int } // T1のunderlying typeはstruct{ number int } T2 int // T2のunderlying typeはint T2 int // T2のunderlying typeはint ) ) func main() { func main() { // underlying typeが同じ(struct{ number int })であり、 // underlying typeが同じ(struct{ number int })であり、 // なおかつ、一方(struct{ number int }{number: 1})がdefined typeではないため代入可能である // なおかつ、一方(struct{ number int }{number: 1})がdefined typeではないため代入可能である var t1 T1 = struct{ number int }{number: 1} var t1 T1 = struct{ number int }{number: 1} fmt.Println(t1) // {1} fmt.Println(t1) // {1} // underlying typeは同じ(int)だが、T2およびintがともにdefined typeであるため代入不可能である // underlying typeは同じ(int)だが、T2およびintがともにdefined typeであるため代入不可能である var t2 T2 = one var t2 T2 = one } } Run 10 10

Slide 11

Slide 11 text

2 2 underlying type defined type underlying type defined type DQNEO Nobishii DQNEO Nobishii underlying type by. DQNEO underlying type by. DQNEO (https://docs.google.com/presentation/d/1JUiZ-SdXbFvi8_hJZ-ouJbDdEJGT- (https://docs.google.com/presentation/d/1JUiZ-SdXbFvi8_hJZ-ouJbDdEJGT- op827O7V7HUAWU/edit#slide=id.p) op827O7V7HUAWU/edit#slide=id.p) defined type by. Nobishii defined type by. Nobishii (https://docs.google.com/presentation/d/1JSsrv404ZDJSnxp4UcJ3iVYDJAiT3RyETMe9AvbkxuY/edit#slide=id.gbb52947b14_0_62) (https://docs.google.com/presentation/d/1JSsrv404ZDJSnxp4UcJ3iVYDJAiT3RyETMe9AvbkxuY/edit#slide=id.gbb52947b14_0_62) 11 11

Slide 12

Slide 12 text

3 3 T x T T x T package main package main import "fmt" import "fmt" type ( type ( T1 interface{} T1 interface{} T2 interface { T2 interface { String() string String() string } } ) ) func main() { func main() { x := 1 x := 1 var t1 T1 = x // xはインターフェースT1を満たしている var t1 T1 = x // xはインターフェースT1を満たしている fmt.Println(t1) // 1 fmt.Println(t1) // 1 var t2 T2 = x // xはインターフェースT2を満たしていないので代入不可能である var t2 T2 = x // xはインターフェースT2を満たしていないので代入不可能である } } Run 12 12

Slide 13

Slide 13 text

4 4 x T channel type x T channel type && T x V && T x V && T V defined type && T V defined type package main package main import "fmt" import "fmt" type T <-chan int // Tはchannel type type T <-chan int // Tはchannel type func main() { func main() { x1 := make(chan int, 1) // x1は要素の型がintの双方向チャネル x1 := make(chan int, 1) // x1は要素の型がintの双方向チャネル var t1 T = x1 // t1およびx1の要素の型は同じ(int) var t1 T = x1 // t1およびx1の要素の型は同じ(int) fmt.Println(t1) // アドレス情報 fmt.Println(t1) // アドレス情報 x2 := make(chan string, 1) // x2は要素の型がstringの双方向チャネル x2 := make(chan string, 1) // x2は要素の型がstringの双方向チャネル var t2 T = x2 // t2およびx2の要素の型が異なるので代入不可能である var t2 T = x2 // t2およびx2の要素の型が異なるので代入不可能である } } Run 13 13

Slide 14

Slide 14 text

5 5 x nil x nil T , , , , T , , , , package main package main type ( type ( Tp *int Tp *int Tf func() Tf func() Ts []int Ts []int Tm map[int]int Tm map[int]int Tc chan int Tc chan int Ti interface{} Ti interface{} ) ) func main() { func main() { var _ Tp = nil // Tpはポインタ && 値(x)はnil var _ Tp = nil // Tpはポインタ && 値(x)はnil var _ Tf = nil // Tfは関数 && 値(x)はnil var _ Tf = nil // Tfは関数 && 値(x)はnil var _ Ts = nil // Tsはスライス && 値(x)はnil var _ Ts = nil // Tsはスライス && 値(x)はnil var _ Tm = nil // Tmはマップ && 値(x)はnil var _ Tm = nil // Tmはマップ && 値(x)はnil var _ Tc = nil // Tcはチャネル && 値(x)はnil var _ Tc = nil // Tcはチャネル && 値(x)はnil var _ Ti = nil // Tiはインターフェース && 値(x)はnil var _ Ti = nil // Tiはインターフェース && 値(x)はnil } } Run 14 14

Slide 15

Slide 15 text

5 5 x nil x nil package main package main import "fmt" import "fmt" type T *int type T *int func main() { func main() { var x func() // 関数型のゼロ値はnil var x func() // 関数型のゼロ値はnil fmt.Println(x) // fmt.Println(x) // var t T = x // xはnilだが事前宣言された識別子としてのnilではないため代入不可能である var t T = x // xはnilだが事前宣言された識別子としてのnilではないため代入不可能である } } Run 15 15

Slide 16

Slide 16 text

6 6 x T untyped constant x T untyped constant 16 16

Slide 17

Slide 17 text

num num → Constants → Constants Go Constants Go Constants (https://golang.org/ref/spec#Constants) (https://golang.org/ref/spec#Constants) package main package main import "fmt" import "fmt" const num = 1 // 型が宣言されていない=型無し定数 const num = 1 // 型が宣言されていない=型無し定数 func main() { func main() { var i int = num // 暗黙的な変換により定数numはint型として扱われる var i int = num // 暗黙的な変換により定数numはint型として扱われる fmt.Printf("%T", i) // int fmt.Printf("%T", i) // int } } Run 17 17

Slide 18

Slide 18 text

6 6 x T untyped constant x T untyped constant package main package main import "fmt" import "fmt" // 型が宣言されていない=型無し定数 // 型が宣言されていない=型無し定数 const x = 1000 const x = 1000 func main() { func main() { var t1 int = x // x=1000はintで表現可能である var t1 int = x // x=1000はintで表現可能である fmt.Println(t1) // 1000 fmt.Println(t1) // 1000 var t2 int8 = x // x=1000はint8(-128~127)で表現できないため代入不可能である var t2 int8 = x // x=1000はint8(-128~127)で表現できないため代入不可能である } } Run 18 18

Slide 19

Slide 19 text

19 19

Slide 20

Slide 20 text

Assignable Assignable 1. 値xの型が型Tとidenticalである 1. 値xの型が型Tとidenticalである 2. 型Tと値xの型Vが同じunderlying typeを持つ 2. 型Tと値xの型Vが同じunderlying typeを持つ && 型Tまたは型Vのいずれかがdefined typeでない && 型Tまたは型Vのいずれかがdefined typeでない 3. 型Tはインターフェースであり、値xがインターフェースTを満たしている 3. 型Tはインターフェースであり、値xがインターフェースTを満たしている 4. 値xは双方向チャネルであり、型Tはchannel typeである 4. 値xは双方向チャネルであり、型Tはchannel typeである && 型Tおよび値xの型Vが持つ要素の型が同じである && 型Tおよび値xの型Vが持つ要素の型が同じである && 型Tまたは型Vのいずれかがdefined typeでない && 型Tまたは型Vのいずれかがdefined typeでない 5. 値xは事前宣言された識別子としてのnilであり、 5. 値xは事前宣言された識別子としてのnilであり、 型Tはポインタまたは関数, スライス, マップ, チャネル, インターフェースのどれかである 型Tはポインタまたは関数, スライス, マップ, チャネル, インターフェースのどれかである 6. 値xは型Tの値によって表現可能な型無し定数(untyped constant)である 6. 値xは型Tの値によって表現可能な型無し定数(untyped constant)である 20 20

Slide 21

Slide 21 text

Nobishii DQNEO Nobishii DQNEO 21 21

Slide 22

Slide 22 text

Thank you Thank you yyh-gl yyh-gl @yyh_gl @yyh_gl (http://twitter.com/yyh_gl) (http://twitter.com/yyh_gl)