Key Type 으로 가능 한 것들은 아래와 같다
기본 자료형 , String, Pointer 형식 (결국 정수형), Struct, array
map,slice
value Type은 아무거나 가능하다.
type Vertex struct { Lat, Long float64 } var m = map[string]Vertex{ "Bell Labs": {40.68433, -74.39967}, "Google": {37.42202, -122.08408}, } func main() { fmt.Println(m) } ========================================================================= var m = map[string]Vertex{ "Bell Labs": Vertex{40.68433, -74.39967}, "Google": Vertex{37.42202, -122.08408}, } func main() { fmt.Println(m) } // map[Bell Labs:{40.68433 -74.39967} Google:{37.42202 -122.08408}]
type Any interface{} type JsonObject map[string]Any func main() { data, _ := json.MarshalIndent(JsonObject{ "id": 1, "name": "sjs", "sub": JsonObject{ "hello": "world", }, }, "", "\t") fmt.Println(string(data)) } // { // "id": 1, // "name": "sjs", // "sub": { // "hello": "world" // } // }
func compute(fn func(float64, float64) float64) float64 { return fn(3, 4) } func main() { hypot := func(x, y float64) float64 { return math.Sqrt(x*x + y*y) } fmt.Println(hypot(5, 12)) fmt.Println(compute(hypot)) fmt.Println(compute(math.Pow)) } // 13 // 5 // 81 ( 3*3*3*3 )
func adder() func(int) int { sum := 0 return func(x int) int { sum += x return sum } } func main() { pos, neg := adder(), adder() for i := 0; i < 10; i++ { fmt.Println( pos(i), neg(-2*i), ) } } // 0 0 // 1 -2 // 3 -6 // 6 -12 // 10 -20 // 15 -30 // 21 -42 // 28 -56 // 36 -72 // 45 -90
type Vertex struct { X, Y float64 } func (v Vertex) Abs() float64 { return math.Sqrt(v.X*v.X + v.Y*v.Y) } func main() { v := Vertex{3, 4} fmt.Println(v.Abs()) } // 5
type Vertex struct { X, Y float64 } func Abs(v Vertex) float64 { return math.Sqrt(v.X*v.X + v.Y*v.Y) } func Scale(v *Vertex, f float64) { v.X = v.X * f v.Y = v.Y * f } func main() { v := Vertex{3, 4} Scale(&v, 10) // <= 포인터 값을 넘겨줘야함 fmt.Println(Abs(v)) } // 50
type Vertex struct { X, Y float64 } func (v *Vertex) Scale(f float64) { v.X = v.X * f v.Y = v.Y * f } func ScaleFunc(v *Vertex, f float64) { v.X = v.X * f v.Y = v.Y * f } func main() { v := Vertex{3, 4} v.Scale(2) ScaleFunc(&v, 10) p := &Vertex{4, 3} p.Scale(3) ScaleFunc(p, 8) fmt.Println(v, p) }
type Vertex struct { X, Y float64 } func (v *Vertex) Scale(f float64) { v.X = v.X * f v.Y = v.Y * f } func Scale(v *Vertex, f float64) { v.X = v.X * f v.Y = v.Y * f } func main() { v := Vertex{3, 4} v.Scale(2) Scale(&v, 10) p := &Vertex{4, 3} p.Scale(3) Scale(p, 8) fmt.Println(v, p) Vertex{3, 4}.Scale(2) <== 컴파일 에러 (&Vertex{3, 4}.Scale(2)) }
값 리시버를 사용 하는 이유 Readonly로 관리 가능
포인터 리시버를 사용 하는 이유 해당 인스턴스 값을 변경 가능 큰 구조체나 데이터의 값복사를 방지 할 수 있음
type I interface { M() } type T struct { S string } func (t *T) M() { if t == nil { fmt.Println("당신의 T nil로 대체 된건 아니고 nil 이다.") return } fmt.Println(t.S) } func main() { var i I // i.M() runtime error var t *T i = t describe(i) i.M() i = &T{"hello"} describe(i) i.M() } func describe(i I) { fmt.Println("(%v, %T)\n", i, i) } // (%v, %T) // <nil> <nil> // 당신의 T nil로 대체 된건 아니고 nil 이다. // (%v, %T) // &{hello} &{hello} // hello
type I interface { M() } func main() { var i I describe(i) i.M() } func describe(i I) { fmt.Println("(%v, %T)\n", i, i) }
func main() { var i interface{} = "HELLO" s := i.(string) fmt.Println(s) s, ok := i.(string) fmt.Println(s, ok) f, ok := i.(float64) fmt.Println(f, ok) f = i.(float64) //panic fmt.Println(f) } // HELLO // HELLO true // 0 false // panic: interface conversion: interface {} is string, not float64 // goroutine 1 [running]: // main.main() // /mnt/c/Users/sjs/Desktop/wecode/go/helloworld/main.go:20 +0x165 // exit status 2
func do(i interface{}) { switch v := i.(type) { case int: fmt.Printf("Twice %v is %v\n", v, v*2) case string: fmt.Printf("%q is %v bytes long\n", v, len(v)) default: fmt.Printf("I don't know about type %T!\n", v) } } func main() { do(21) do("hello") do(true) } // Twice 21 is 42 // "hello" is 5 bytes long // I don't know about type bool!
type Person struct { Name string Age int } func (p Person) String() string { return fmt.Sprintf("%v (%v years)", p.Name, p.Age) } func main() { a := Person{"Arthur Dent", 42} z := Person{"Zaphod Beeblebrox", 9001} fmt.Println(a, z) } // Arthur Dent (42 years) Zaphod Beeblebrox (9001 years) type Stringer interface { String() string }
Stringer 는 자신을 문자열로 설명할 수 있는 타입입니다. fmt 패키지 및 기타 여러 패키지는 값을 출력하기 위해 이 인터페이스를 사용합니다.
error 타입은 fmt.Stringer 와 유사한 내장 인터페이스 입니다
type error interface { Error() string }
io 패키지는 데이터 스트림의 읽기를 나타내는 io.Reader 인터페이스를 지정합니다.
type Reader interface { Read(p[]byte)(n int, err error) }
type image interface { ColorModel() color.Model Bounds() Rectangle At(x int, y int) color.Color }