Upgrade to Pro — share decks privately, control downloads, hide ads and more …

入門Go言語仕様輪読会 Assignability / Go Language Specification Assignability

yyh_gl
March 18, 2021

入門Go言語仕様輪読会 Assignability / Go Language Specification Assignability

入門Go言語仕様輪読会 #2 で発表した内容です。
https://gospecreading.connpass.com/event/205420/

go-talks上で見てもらうとスライド内のコードを実行できます!
https://go-talks.appspot.com/github.com/yyh-gl/slide-decks/210318_gospecreading_assignability.slide

yyh_gl

March 18, 2021
Tweet

More Decks by yyh_gl

Other Decks in Technology

Transcript

  1. 2 2

  2. 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
  3. 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
  4. 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
  5. 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
  6. 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
  7. 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
  8. 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
  9. 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
  10. 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) // <nil> fmt.Println(x) // <nil> var t T = x // xはnilだが事前宣言された識別子としてのnilではないため代入不可能である var t T = x // xはnilだが事前宣言された識別子としてのnilではないため代入不可能である } } Run 15 15
  11. 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
  12. 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
  13. 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