Save 37% off PRO during our Black Friday Sale! »

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

B932b972f9334d4d333224468f3f84d9?s=47 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

B932b972f9334d4d333224468f3f84d9?s=128

yyh_gl

March 18, 2021
Tweet

Transcript

  1. Assignability Assignability Go Go 18 March 2021 18 March 2021

    yyh-gl yyh-gl
  2. 2 2

  3. 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
  4. 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
  5. Assignability Assignability 5 5

  6. Assignability = Assignability = Go 6 Go 6 6 6

  7. Assignable Assignable 7 7

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

    T Assignable 8 8
  9. 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
  10. 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
  11. 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
  12. 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
  13. 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
  14. 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
  15. 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
  16. 6 6 x T untyped constant x T untyped constant

    16 16
  17. 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
  18. 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
  19. 19 19

  20. 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
  21. Nobishii DQNEO Nobishii DQNEO 21 21

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