Skip to content

Instantly share code, notes, and snippets.

@changtimwu
Last active August 29, 2015 14:00
Show Gist options
  • Save changtimwu/11270600 to your computer and use it in GitHub Desktop.
Save changtimwu/11270600 to your computer and use it in GitHub Desktop.
go study notes

var:= 的差異

  • := 一定要給初值
b:=3
baz:= []int {3,4,5}
baz:= [3]int   // error! 缺乏初值
  • var 可以給初值也可以不給
var a = int(3) // 給初值
var b          // 不給初值
println("b initial val=", b)   //會有預設初值 0
b = 3          // 事後 assign
a := 3         // error! :=是宣告, 已經宣告過了, 不可以重複宣告

var az []int=[]int {3,4,5}  //給初值
var bz []int                 //沒給初值
bz = []int{5, 6, 7, 9, 3}    // 事後給
bz = []int{3, 7, 9, 11, 5}   // 可以重複給, 原本內容會被gc?
  • 在function 外只能用 var
package main

import "fmt"

type Vertex struct {
    Lat, Long float64
}

var m map[string]Vertex

func main() {
    m = make(map[string]Vertex)
    m["Bell Labs"] = Vertex{
        40.68433, -74.39967,
    }
    fmt.Println(m["Bell Labs"])
}

array 的 assign

var ary [5]int
ary[1]=33 // ok
ary[6]=77 // error! out of range
ary=[5]int {7,8,9,10,11} // ok!
ary=[3]int {3,4,5}  //error! 不同長度的array會被視為不同type,  [3]int 不能直接assign給 [5]int

var ary1 []int
ary1=[]int {3,4,5}  //ok

ary1=[]int {4,5,6,7} // ok
ary1=[2]int {1,2} // error! 會被視為不同type, [2]int 與 []int 不能直接assign, 
ary1=[]int {1,2} // ok

GO的array 與C array的差異

  • http://golang.org/doc/effective_go.html#arrays
    • Arrays are values. Assigning one array to another copies all the elements.
    • In particular, if you pass an array to a function, it will receive a copy of the array, not a pointer to it.
    • The size of an array is part of its type. The types [10]int and [20]int are distinct. 長度不同type就不同
  • 資料很大記得改用pointer to array or slice
func passptr(aryptr *[4]int) {
    aryptr[1] = 999 // reference through pointer is the same way as accessing variable
}

func passslice(arysl []int) {
    arysl[1] += 1 // reference through pointer is the same way as accessing variable
}

func array_pass() {
    ary1 := [4]int{4, 5, 6, 7}
    passptr(&ary1)
    fmt.Println("ary1 becomes ", ary1)
    passslice(ary1[:])
    fmt.Println("ary1 becomes ", ary1)
}
  • most array programming in Go is done with slices rather than simple arrays.
  • _If the data exceeds the capacity, the slice is reallocated. _
func fixed_length_array_not_appendable() {                                                                
    a := [2]string{"John", "Paul"}
    fmt.Println("len(a)=", len(a), "cap(a)=", cap(a))
    //a = append(a, "mary") // array size 固定, 不可以append 
}
func append_to_slice_pointing_array() {
    a := [2]string{"John", "Paul"}
    asl := a[:]

    fmt.Println("len(asl)=", len(asl), "cap(asl)=", cap(asl))
    asl = append(asl, "mary") // trigger an reallocation
    // slice 可以自由 append 萬一實際容量不夠, 它會自動realloc 
    fmt.Println("len(asl)=", len(asl), "cap(asl)=", cap(asl))
    fmt.Println("asl=", asl)
}

new 跟make的差異

  • new 都是單一值
v1:= new(Vertex)
  • make可以拿來生成slice or map
u:=make(map[string]int) 
bazb:=make([]int,5)
  • 都不能設初值
v1:= new(Vertex){3,4} //error
bazb:=make([]int,5){1,2,3,4,5} //error
  • 下列四個是否一樣?
var ary1 [5]int
ary2:=[5]int{}
var ary3 = make([]int, 5)
ary4:=make([]int,5)

result

ary1 type=[5]int, len=5, content=[0 0 0 0 0]
ary2 type=[5]int, len=5, content=[0 0 0 0 0]
ary3 type=[]int, len=5, content=[0 0 0 0 0]
ary4 type=[]int, len=5, content=[0 0 0 0 0]
  • make 與直接宣告的差異
var ary1 [5]int
fmt.Printf("ary1 type=%T, len=%d, content=%v\n", ary1, len(ary1), ary1)
var ary2 = make([]int, 5)
fmt.Printf("ary2 type=%T, len=%d, content=%v\n", ary2, len(ary2), ary2)                         
// output 
//ary1 type=[5]int, len=5, content=[0 0 0 0 0]
//ary2 type=[]int, len=5, content=[0 0 0 0 0]
  • [] 其實叫做 slice, 彈性比fixed length array 高
    var ary1 []int = []int{1, 2}
    fmt.Printf("ary1 type=%T, len=%d, content=%v\n", ary1, len(ary1), ary1)
    // result: ary1 type=[]int, len=2, content=[1 2]
    
    ary1 = append(ary1, 44)
    fmt.Printf("ary1 type=%T, len=%d, content=%v\n", ary1, len(ary1), ary1)
    // result: ary1 type=[]int, len=3, content=[1 2 44]

    var ary2 [2]int
    fmt.Printf("ary2 type=%T, len=%d, content=%v\n", ary2, len(ary2), ary2)
    // result: ary2 type=[2]int, len=2, content=[0 0]
    
    ary2 = append(ary2, 44) // error! first argument to append must be slice; have [2]int
     

Slice

  • 參考 http://blog.golang.org/slices
  • 重點節錄 it is not a pointer to the first array element (as would be the case in C). This means that when you assign or pass around an array value you will make a copy of its contents. (To avoid the copy you could pass a pointer to the array, but then that's a pointer to an array, not an array.
  • so
  ary1 := [4]int{4, 5, 6, 7}
  ary2 := ary1
  ary1[2] = 999                                                                                   
  fmt.Println("ary1=", ary1, "ary2=", ary2)
  //result
  ary1= [4 5 999 7] ary2= [4 5 6 7]
  • [...] 代表自動算count element , 跟[] (slice) 意義不一樣
    ary1 := [...]int{4, 5, 6, 7}
    ary2 := ary1
    ary1[2] = 999
    fmt.Println("ary1=", ary1, "ary2=", ary2)                                                       
    fmt.Printf("ary1's type = %T , ary2's type = %T\n", ary1, ary2)
    //result:
    //ary1= [4 5 999 7] ary2= [4 5 6 7]
    //ary1's type = [4]int , ary2's type = [4]int
  • pointer to array 長這樣
    ary1 := [4]int{4, 5, 6, 7}
    aryptr1 := new([4]int)
    aryptr1 = &ary1
    fmt.Printf("aryptr1's type = %T\n", aryptr1)
    aryptr1[1] = 999 // reference through pointer is the same way as accessing variable
    fmt.Println("ary1 becomes ", ary1)
    aryptr1[5] = 99 // error!  Unlike C, in Go pointers have range protection
  • interface 當func parameter 的type, caller可以傳pointer 或var本身, it dependents the variable's type implementation
type Person interface {
    getage() int
}

type Farmer struct {
    age int
}

func (f *Farmer) getage() int {
    return f.age
}

func showage(p Person) {                                                                        
    println("the age is ", p.getage())
}

type Carpenter struct {
    age int
}

func (cp Carpenter) getage() int {
    return cp.age
}


func main() {
    f := Farmer{age: 10}
    showage(&f)
    //showage(f) // error Farmer doesn't implement Person

    cp := Carpenter{age: 12}
    showage(cp)
    //showage(&cp) // error! *Carpenter doesn't implement Person
}
  • 這個例子中我們可以說
    • *Farmer implement了 Person interface, 但 Farmer 並沒有
    • Carpenter implement了 Person interface, 但 *Carpenter 並沒有
  • 為你的type定義String function, 可以讓你的type用fmt.Println印出來
type CBack struct {
    id int
    d  string
}

func (cb CBack) String() string {
    return fmt.Sprintf("id=%d, d=%s", cb.id, cb.d)
}

func main () {
    cb := CBack{id: 3, d: "hello"}
    fmt.Println("cb is ", cb)
}

Type Casting

@changtimwu
Copy link
Author

There is no pointer to interface.

type human interface {
    getAge() int
}
// you would get error 
func f1(h *human) {
    fmt.Println("h.age=", h.getAge())
}

plain interface argument can accept both struct and pointer to struct

type human interface {
    getAge() int
}
func f1(h human) {
    fmt.Println("h.age=", h.getAge())
}
type student struct {
    age int
}
func (student) getAge() int {
    return 17
}
func main() {
    h := student{33}
    f1(h)  // ok!
    f1(&h)  // ok!
}  

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment