golang base (two)
本文最后更新于:星期四, 一月 20日 2022, 11:45 晚上
map
m := map [string ]int {"one" :1 ,"two" :2 ,"three" :3 } t.Log(m, len (m)) m1 := map [string ]int {} m1["one" ] = 1 t.Log(m1, len (m1)) m2 :=make (map [string ]int ,5 ) t.Log(m2,len (m2))
1 2 3 4 5 6 7 8 9 10 11 12 m3 := map [int ]int {} t.Log(m3[1 ]) m3[2 ] = 0 t.Log(m3[2 ]) m3[3 ] = 0 ;if v, ok := m3[3 ]; ok { t.Log(v, "key 3 is exist." ) } else { t.Log("KEY 3 is not existing." ) }
1 2 3 4 m := map [string ]int {"one" : 1 , "two" : 2 , "three" : 3 }for k, v := range m { t.Log(k, "=>" , v) }
1 2 3 4 5 6 7 8 9 10 11 m := map [int ]func (op int ) int {} m[1 ] = func (op int ) int { return op } m[2 ] = func (op int ) int { return op * op } m[3 ] = func (op int ) int { return op *op* op } t.Log(m[1 ](2 ),m[2 ](2 ),m[3 ](2 ))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 mySet := map [int ]bool {} mySet[1 ] = true mySet[3 ] = true n:= 3 if mySet[n]{ t.Logf("%d is existing" ,n) }else { t.Logf("%d is not existing" ,n) t.Log(mySet[n]) } t.Log(len (mySet)) delete (mySet, n) if mySet[n]{ t.Logf("%d is existing" ,n) }else { t.Logf("%d is not existing" ,n) t.Log(mySet[n]) }
字符串
string
是数据类型,不是引用或是指针类型,零值为空字符串
string
是 只读的 byte
slice
, len
函数可以展示它所包含的 byte
string
的 byte
数组可以存放任何数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 var s string t.Log(s) s = "hello" t.Log(len (s)) s = "\xE4\xB8\xA5" t.Log(s,len (s)) s ="中" t.Log(len (s)) c:=[]rune (s) t.Log(len (c)) t.Log("rune size :" , unsafe.Sizeof(c)) t.Logf("中 unicode %x" ,c[0 ]) t.Logf("中 UTF8 %x" ,s) s = "中华人民共和国" for _,v := range s { t.Logf("%[1]c %[1]x" ,v) } s = "A,B,C" parts := strings.Split(s,"," ) t.Logf("%T" , parts)for _,v := range parts{ t.Logf("%T" , v) } t.Log(strings.Join(parts,"-" )) s1 := strconv.Itoa(10 ) t.Log("str " + s1)if s2,err := strconv.Atoi(s1);err == nil { t.Log(10 +s2) }
函数
函数是一等公民
函数有多个返回值
所有参数都是值传递:slice
map
channel
会有传引用的错觉
函数可以作为变量的值
函数可以作为参数和返回值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 func returnMultiValues () (a, b int ) { return rand.Intn(10 ), rand.Intn(20 ) }func timeSpent (inner func (op int ) int ) (func (op int ) int ) { return func (n int ) int { start := time.Now() ret := inner(n) fmt.Println("time Spent:" ,time.Since(start).Seconds()) return ret } }func slowFun (op int ) int { time.Sleep(time.Second*1 ) return op }func TestFn (t *testing.T) { i, l := returnMultiValues() t.Log(i, l) tsSF := timeSpent(slowFun) t.Log(tsSF(10 )) }
可变长参数与 defer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 func Sum (ops ...int ) (res int ) { res = 0 for _,v := range ops{ res += v } return }func TestFn1 (t *testing.T) { t.Log(Sum(1 ,2 ,3 ,4 ,5 )) t.Log(Sum(1 ,2 ,3 ,4 ,5 ,6 )) }func Clear () { defer fmt.Println("errs" ) fmt.Println("close" ) panic ("err" ) }func Clear2 () { defer fmt.Println("errs2" ) fmt.Println("close2" ) panic ("err" ) }func TestDefer (t *testing.T) { defer Clear() defer Clear2() fmt.Println("Start" ) panic ("err" ) }
面向对象 封装数据和行为(方法) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 type Employee struct { Id string Name string Age int }func TestCreateEmployeeObj (t *testing.T) { e:= Employee{"0" ,"张三" ,23 } e1 := Employee{Id:"张三" ,Name:"李四" ,Age:25 } e2 := new (Employee) e2.Age = 29 e2.Name = "王五" e2.Id = "3" t.Log(e) t.Log(e1) t.Log(e2) t.Logf("e is %T" , e) t.Logf("e2 is %T" , e2) }
1 2 3 4 5 6 7 8 9 10 11 func (e *Employee) String () string { fmt.Printf("Address is %x\n" , unsafe.Pointer(&e.Name)) return fmt.Sprintf("ID:%s-Name:%s-Age:%d" , e.Id, e.Name, e.Age) }func (e Employee) String () string { fmt.Printf("Address is %x\n" , unsafe.Pointer(&e.Name)) return fmt.Sprintf("ID:%s-Name:%s-Age:%d" , e.Id, e.Name, e.Age) }
接口的定义
非入侵的,实现不依赖接口定义
所以接口的定义可以包含在接口使用者包内
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 type Programmer interface { WriterHelloWorld() string }type GoProgrammer struct { }func (to *GoProgrammer) WriterHelloWorld () string { return "fmt.Println(\"hello world!\")" }func TestClient (t *testing.T) { var p Programmer p = new (GoProgrammer) t.Log(p.WriterHelloWorld()) }
接口变量
声明 var prog Coder = &GoPaogrammer{}
prog 由两部分组成
type GoPaogrammer struct{}
数据类型
&GoPaogrammer{}
数据实例
继承与组合
golang 中组合的成分高于继承,甚至可以说没有一般语言的继承概念
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 type Pet struct { }func (p *Pet) Speck () { fmt.Println("..." ) }func (p *Pet) SpeckTo (host string ) { p.Speck() fmt.Println(" " , host) }type Dog struct { Pet }func (d *Dog) Speck () { fmt.Println("www" ) d.SpeckTo("laowan" ) }func TestInherit (t *testing.T) { var dog = new (Dog) dog.Speck()
接口与多态 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 type Code string type Programmer interface { WriterHelloWorld() Code }type GoProgrammer struct { }func (to *GoProgrammer) WriterHelloWorld () Code { return "fmt.Println(\"hello world!\")" }type JavaProgrammer struct { }func (to *JavaProgrammer) WriterHelloWorld () Code { return "fmt.Println(\"hello world!\")" }func WriterFirstProgrammer (programmer Programmer) { fmt.Printf("%T %v\n" , programmer, programmer.WriterHelloWorld()) }func TestPolymorphism (t *testing.T) { goProg := new (GoProgrammer) javaProg := new (JavaProgrammer) WriterFirstProgrammer(goProg) WriterFirstProgrammer(javaProg) }
空接口与断言
空接口可以表示任何类型
通过断言来将空接口转换为指定类型
v,ok := p.(int) // ok=true 时为转换成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 func DoSomething (p interface {}) { switch i := p.(type ) { case int : fmt.Println("Integer" , i) return case string : fmt.Println("String" , i) return default : fmt.Println("unKnow Type" ) } }func TestDoSomething (t *testing.T) { DoSomething(10 ) DoSomething("10" ) DoSomething('1' ) }
Go接口最佳实践