Pointer
Data types in Go:
- primitive
    
stringintboolfloat
 - advanced
    
structarrayslicemapchanfunc
 
The pointers in Go are for reference basically to determine whether passing by value or by reference.
The memory includes stack and heap. stack is used to store simple-type data that are currently used, like those primitive types in Go. Data of these types occupy less memory and are easy to recycle. The space for their value and pointer are comparable so can be copied directly. Garbage collection is also easy to optimize.
Complex data types are usually stored in heap, since they need relatively large memory. Gabage collection is less frequent and costs more. So passing reference is more economic since it avoids expensive copy operation; saves memory and improve efficiency.
So pointer can be used in 3 cases as below:
- Need to change value
 - Avoid copy
 - Save memory
 
In Go, we can actually use slice, map and chan directly without considering pointer or value, since they all pass reference. However, we need to pay attention to struct. It’s a little more complicated.
struct
For func, passing type is determined by function argument. It will report error if wrong argument type.
func passVal(s struct){}
func passRef(s *struct){}
For method, receiver can be pointer or value. If receiver is value, we pass by value, thus method itself cannot modify outside variable. However, It’s recommend to use pointer as receiver in order to modify value and avoid large object copy.
type MyPoint struct {
    X int
    Y int
}
 
func printFuncValue(p MyPoint){
    p.X = 1
    p.Y = 1
    fmt.Printf(" -> %v", p)
}
 
// input should be pointer like pp (type MyPoint), cannot use just p
func printFuncPointer(pp *MyPoint){
    pp.X = 1 // should be actually (*pp).X, but a syntactic sugar here
    pp.Y = 1
    fmt.Printf(" -> %v", pp)
}
 
func (p MyPoint) printMethodValue(){
    p.X += 1
    p.Y += 1
    fmt.Printf(" -> %v", p)
}
 
func (pp *MyPoint) printMethodPointer(){
    pp.X += 1
    pp.Y += 1
    fmt.Printf(" -> %v", pp)
}
Inheritance
Follwing code is an example for inheritance in Go.
- We cannot use a 
Studentobject as typeHuman. - When we do 
student.Drink(),func (s Student) Drink()will be used, thus overrideHumanmethod. - When we do 
student.Eat(),func (h Human) Eat()will be called. Inside the method,func (h Human) Drink()is called instead ofStudent. 
type Being struct {
    IsLive bool
}
type Human struct {
    Being
    Name string
    Age int
}
func (h Human) Eat(){
    fmt.Println("human eating...")
    h.Drink()
}
 
func (h Human) Drink(){
    fmt.Println("human drinking...")
}
type Student struct {
    Human
    Grade int
    Major string
}
func (s Student) Drink(){
    fmt.Println("student drinking...")
}
Interface
Unlike Java, we don’t need to explicitly implement an interface. For following example, as long as an object looks like a duck, walks like a duck, sounds like a duck, then it’s a duck.
interface Duck {
    LooksLikeDuck()
    WalksLikeDuck()
    SoundsLikeDuck()
}
Use type assertion to determine whether an interface is a type
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)
// use it to convert type with an empty interface
v := interface{}(old).(string)
// type switch, perform several assertion at a time
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)
	}
}
Misc
Read and write file
import (
    	"io/ioutil"
	    "os"
)
// read all content of a file without open or close
file, err := ioutil.ReadFile(fileStr)
// create a file, if exists, will empty it
file, err := os.Create(fileStr)
// open a file and writes to end
file, err := os.OpenFile(fileStr, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0600)
Json
import (
    "encoding/json"
    "os"
// writes json of kv pairs to file
type KeyValue struct {
	Key   string
	Value string
}
file, err := os.Open(fileStr)
kv := KeyValue{"hi", "world"}
enc := json.NewEncoder(file)
err3 := enc.Encode(&kv)
file.Close()
// decode json from file
file, err := os.Open(fileStr)
jsonDecoder := json.NewDecoder(file)
var kv *KeyValue
for jsonDecoder.Decode(&kv) == nil {
    //do something
}
file.Close()
    