继续记录一下go课程的练习demo
ch7 Map
package my_map
import "testing"
func TestInitMap(t *testing.T) {
m1 := map[int]int{1: 1, 2: 4, 3: 9}
t.Log(m1[2])
t.Logf("len m1=%d", len(m1))
m2 := map[int]int{}
m2[4] = 16
t.Logf("len m2=%d", len(m2))
m3 := make(map[int]int, 10)
t.Logf("len m3=%d", len(m3))
}
/**
map初始化时候,获取值时候 取到不存在key时返回0
在访问的 Key 不存在时,仍会返回零值,不能通过返回 nil 来判断元素是否存在
*/
func TestAccess(t *testing.T) {
m1 := map[int]int{}
//返回0
t.Log(m1[1])
m1[2] = 0
t.Log(m1[2])
//怎么区分是没有key还是值为0
//使用if的返回值,返回的两个参数,第一个参数为值,第二个boolean值
m1[3]=0
if v, ok := m1[3]; ok {
t.Logf("Key 3 value is %d", v)
} else {
t.Log("key 3 is not existing")
}
}
/**
map遍历 使用range
*/
func TestTravelMap(t *testing.T) {
m1 := map[int]int{1: 1, 2: 4, 3: 9}
for k,v:=range m1{
t.Log(k,v)
}
}
ch8 Map扩展
package map_ext_test
import "testing"
/**
用函数作为value值
*/
func TestMapWithFunValue(t *testing.T) {
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))
}
/**
Go 的内置集合中没有 Set 实现, 可以 map[type]bool
*/
func TestMapForSet(t *testing.T) {
mySet:= map[int]bool{}
mySet[1] = true
n:=1
if mySet[n]{
t.Logf("%d is extising",n)
}else {
t.Logf("%d is not extising",n)
}
mySet[3]=true
t.Log(len(mySet))
delete(mySet,1)
if mySet[n]{
t.Logf("%d is extising",n)
}else {
t.Logf("%d is not extising",n)
}
}
ch9 字符串string操作
package string_test
import (
"strconv"
"strings"
"testing"
)
func TestStringFn(t *testing.T) {
s := "A,B,C"
parts := strings.Split(s, ",")
for _, part := range parts {
t.Log(part)
}
t.Log(strings.Join(parts,"-"))
}
func TestStringConv(t *testing.T) {
s:=strconv.Itoa(10)
//转字符串
t.Log("str"+s)
//字符串转整型
if i,err:=strconv.Atoi("10");err==nil{
t.Log(10+i)
}
}
package string_test
import "testing"
/**
字符串常用包
*/
func TestString(t *testing.T){
var s string
t.Log(s)
s = "hello"
t.Log(len(s))
s="\xE4\xB8\xA5"
t.Log(s)
s="中"
t.Log(len(s))
/**
rune(取出字符串的uincode)
*/
c:=[]rune(s)
t.Logf("中 unicode %x",c[0])
//e4b8ad
t.Logf("中 UTF8 %x",s)
}
func TestStringToRune(t *testing.T) {
s:="中华人民共和国"
for _,c:=range s{
//以百分号c格式化 以百分号d格式化,[1]标识匹配第一个参数 可以用来遍历字符集
t.Logf("%[1]c %1[1]x",c)
}
}
ch10 函数
package fn_test
import (
"fmt"
"math/rand"
"reflect"
"strconv"
"testing"
"time"
)
func returnMultiValues() (int, int) {
return rand.Intn(10), rand.Intn(20)
}
/*
返回一个函数运行的时长
*/
func timeSpent(inner func(op int) int) func(op int) int {
ret := func(n int) int {
start := time.Now()
ret := inner(n)
fmt.Println("time spent:", time.Since(start).Seconds())
return ret
}
return ret
}
func slowFun(op int) int {
time.Sleep(time.Second * 1)
return op
}
func fastFun(op int) int {
a := strconv.Itoa(op) + "10"
//字符串转整型
var b int
if i, err := strconv.Atoi(a); err == nil {
b = i
}
return b
}
func Clear() {
fmt.Println("Clear resources.")
}
/**
defer 延迟函数,相当于finally
*/
func TestDefer(t *testing.T) {
//
defer Clear()
fmt.Println("Start")
//跑出异常,panic执行后defer仍会执行
panic("err")
}
//函数的可变参数
func Sum(ops ...int) int {
ret := 0;
for _, op := range ops {
ret += op
}
return ret
}
func TestVarParma(t *testing.T){
t.Log(Sum(1,2,3,5))
t.Log(Sum(1,2,3,4))
}
func TestFn(t *testing.T) {
//只获取一个返回值,使用下划线忽略一个返回值
//a, _ := returnMultiValues()
//t.Log(a)
//获取2个返回值
//a, b := returnMultiValues()
//t.Log(a, b)
tsSF := timeSpent(slowFun)
t.Log("----------", reflect.TypeOf(tsSF))
t.Log(tsSF(10))
//tsFF := timeSpent(fastFun)
//t.Log("----------")
//t.Log(tsFF(20))
}
ch11 接口、方法、自定义类型
接口
package interface_test
import "testing"
/**
Go接口
1. 接⼝为⾮⼊侵性,实现不依赖于接口定义
2. 所以接⼝的定义可以包含在接口使⽤者包内
*/
type Programmer interface {
WriteHelloWorld() string
}
type GoProgrammer struct {
}
/**
Duck Type式接口方式
接口签名一致,就是响应的方法
*/
func (go1 *GoProgrammer) WriteHelloWorld() string {
return "Hello World"
}
//测试接口
func TestClient(t *testing.T) {
var p Programmer
p = new(GoProgrammer)
t.Log(p.WriteHelloWorld())
//接口变量
var prog Programmer = &GoProgrammer{}
/**
prog 类型为:
type GoProgrammer struct{}
prog的数据为:
&GoProgrammer{}
*/
t.Log(prog.WriteHelloWorld())
}
行为 方法
package encapsulation_test
import (
"fmt"
"testing"
"unsafe"
)
/**
结构体定义
*/
type Employee struct {
id string
name string
age int
}
func TestEncap(t *testing.T) {
e := Employee{"aaa", "AAA", 1}
e1 := Employee{id: "bbb", name: "BBB", age: 2}
//注意这⾥返回的引⽤/指针,相当于 e := &Employee{}
e2 := new(Employee)
//与其他主要编程语⾔的差异:通过实例的指针访问成员不需要使⽤->
e2.id = "ccc"
e2.name = "CCC"
e2.age = 3
t.Log(e)
t.Log(e1)
t.Log(e1.id)
t.Log(e2)
t.Log(e2.id)
//输出类型
t.Logf("e is %T", e)
t.Logf("e is %T", &e)
t.Logf("e is %T", e2)
}
/*
行为(方法)定义
*/
//第⼀种定义⽅式在实例对应⽅法被调⽤时,实例的成员会进⾏值复制
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",unsafe.Pointer(&e.name))
// return fmt.Sprintf("ID:%s/Name%s/Age:%d",e.id,e.name,e.age)
//}
func TestStructOperations(t *testing.T) {
e := Employee{"0", "AAA", 1}
//获取地址
fmt.Printf("Address is %x\n",unsafe.Pointer(&e.name))
//调用方法
t.Log(e.String())
//e1 := &Employee{"0", "AAA", 1}
//类型指针实例,调用其成员或者方法时不需要使用箭头函数,直接使用"."
//t.Log(e1.String())
}
自定义类型
package customer_type_test
import (
"fmt"
"testing"
"time"
)
/**
自定义类型
创建一个自定义的类型
*/
type IntConv func(op int) int
/*
返回一个函数运行的时长
*/
func timeSpent(inner IntConv) IntConv {
ret := func(n int) int {
start := time.Now()
ret := inner(n)
fmt.Println("time spent:", time.Since(start).Seconds())
return ret
}
return ret
}
func slowFun(op int) int {
time.Sleep(time.Second * 1)
return op
}
func TestFn(t *testing.T) {
tsSF := timeSpent(slowFun)
t.Log(tsSF(10))
}
ch12 扩展与复合
package extension
import (
"fmt"
"testing"
)
type Pet struct {
}
func (p *Pet) Speak() {
fmt.Println("...")
}
func (p *Pet) SpeakTo(name string) {
p.Speak()//这里会调用自己的Speak方法,不会调用dog的speak方法
fmt.Println("",name)
}
/**
扩展Pet功能为例
*/
type Dog struct {
p *Pet
}
//在父类中不会调用子类的speak方法
//func (aDog *Dog) Speak() {
// fmt.Println("Wang!!!")
// aDog.p.Speak()
//}
//在父类中不会调用子类的speak方法
//func (aDog *Dog) SpeakTo(name string) {
// aDog.p.SpeakTo(name)
//}
//这里和java不同
//子类自己实现speak方法
func (aDog *Dog) Speak() {
fmt.Println("Wang!!!")
}
//子类自己实现speak方法
func (aDog *Dog) SpeakTo(name string) {
aDog.Speak()
fmt.Println("",name)
}
func TestDog(t *testing.T) {
dog:= new(Dog)
dog.SpeakTo("Chao")
}
package extension
import (
"fmt"
"testing"
)
type Pet1 struct {
}
func (p *Pet1) Speak() {
fmt.Println("...")
}
func (p *Pet1) SpeakTo(name string) {
p.Speak() //这里会调用自己的Speak方法,不会调用dog的speak方法
fmt.Println("", name)
}
/**
扩展Pet功能为例
go 中提供了一种匿名嵌套类型的声明
并没有重载方法
内嵌的结构类型不支持重载
*/
type Dog1 struct {
Pet1
}
//在父类中不会调用子类的speak方法
//func (aDog *Dog) Speak() {
// fmt.Println("Wang!!!")
// aDog.p.Speak()
//}
//在父类中不会调用子类的speak方法
//func (aDog *Dog) SpeakTo(name string) {
// aDog.p.SpeakTo(name)
//}
//子类自己实现speak方法
func (aDog *Dog1) Speak() {
fmt.Println("Wang!!!")
}
func TestDog1(t *testing.T) {
//匿名嵌套类型的调用
dog := new(Dog1)
dog.SpeakTo("Chao")
/**
以下声明会报错,Go不支持显示类型转换的
Go中无法支持LSP的原则
*/
//var dog1 Pet1 = new(Dog1)
//dog1.SpeakTo("Chao")
}
ch13 多态 空接口 断言
多态
package polymorphism
import (
"fmt"
"testing"
)
/**
GO的多态
*/
type Code string
type Programmer interface {
WriteHelloWorld() Code
}
type GoProgrammer struct {
}
func (p *GoProgrammer) WriteHelloWorld() Code {
return "fmt.Println(\"Hello World\")"
}
type JavaProgrammer struct {
}
func (p *JavaProgrammer) WriteHelloWorld() Code {
return "fmt.Println(\"Hello World\")"
}
//%T 输出实例类型
func wirteFirstProgram(p Programmer) {
fmt.Printf("%T %v\n", p, p.WriteHelloWorld())
}
func TestPolymorphism(t *testing.T) {
//Programmer是一个接口,只能对应一个指针实例,实例化时也可以
//goProg:=&GoProgrammer{}
//但不可以goProg:=GoProgrammer{}
goProg := new(GoProgrammer)
javaProg := new(JavaProgrammer)
wirteFirstProgram(goProg)
wirteFirstProgram(javaProg)
}
空接口 断言
package empty_interface
import (
"fmt"
"testing"
)
/**
空接口 断言
*/
func DoSomthing(p interface{}) {
//if i,ok:=p.(int);ok{
// fmt.Println("Integer",i)
// return
//}
//
//if s,ok:=p.(string);ok{
// fmt.Println("String",s)
// return
//}
//fmt.Println("Unknow Type")
//使用swtich
switch v:=p.(type) {
case int:
fmt.Println("Integer",v)
case string:
fmt.Println("String",v)
default:
fmt.Println("Unknow Type")
}
}
func TestEmptyInterfaceAssertion(t *testing.T) {
DoSomthing(10)
DoSomthing("10")
}