2176 字
11 分钟
01、
01、
// 反射
type student struct { Name string `json:"name"` Age int `json:"age"`}
func main() { str := `{"name":"周林","age":9000}` var stu1 student json.Unmarshal([]byte(str), &stu1) fmt.Printf("%#v\n", stu1)}02、
// strconv
func main() { // 从字符串中解析出对应的数据 str := "10000" // ret1 := int64(str) ret1, err := strconv.ParseInt(str, 10, 64) if err != nil { fmt.Println("parseint failed, err:", err) return } fmt.Printf("%#v %T\n", ret1, int(ret1))
// Atoi:字符串转换成int retInt, _ := strconv.Atoi(str) fmt.Printf("%#v %T\n", retInt, retInt)
// 从字符串中解析出布尔值 boolStr := "true" boolValue, _ := strconv.ParseBool(boolStr) fmt.Printf("%#v %T\n", boolValue, boolValue) // 从字符串中解析出浮点数 floatStr := "1.234" floatValue, _ := strconv.ParseFloat(floatStr, 64) fmt.Printf("%#v %T\n", floatValue, floatValue)
// 把数字转换成字符串类型 i := 97 // ret2 := string(i) // "a"
ret2 := fmt.Sprintf("%d", i) // "97" fmt.Printf("%#v", ret2) ret3 := strconv.Itoa(i) fmt.Printf("%#v", ret3)}03、
// goroutine
func hello(i int) { fmt.Println("hello", i)}
// 程序启动之后会创建一个主goroutine去执行func main() { for i := 0; i < 1000; i++ { // go hello(i) // 开启一个单独的goroutine去执行hello函数(任务) go func(i int) { fmt.Println(i) // 用的是函数参数的那个i,不是外面的i }(i) } fmt.Println("main") time.Sleep(time.Second) // main函数结束了 由main函数启动的goroutine也都结束了}04、
// waitGroup
func f() { rand.Seed(time.Now().UnixNano()) for i := 0; i < 5; i++ { r1 := rand.Int() // int64 r2 := rand.Intn(10) // 0<= x < 10 fmt.Println(0-r1, 0-r2) }}
func f1(i int) { defer wg.Done() time.Sleep(time.Second * time.Duration(rand.Intn(3))) fmt.Println(i)}
var wg sync.WaitGroup
func main() { // f() // wg.Add(10) for i := 0; i < 10; i++ { wg.Add(1) go f1(i) } // ?如何知道这10个goroutine都结束了 // time.Sleep(?) wg.Wait() // 等待wg的计数器减为0}05、
// GOMAXPROCSvar wg sync.WaitGroup
func a() { defer wg.Done() for i := 0; i < 10; i++ { fmt.Printf("A:%d\n", i) }}
func b() { defer wg.Done() for i := 0; i < 10; i++ { fmt.Printf("B:%d\n", i) }}
func main() { runtime.GOMAXPROCS(1) // 默认CPU的逻辑核心数,默认跑满整个CPU fmt.Println(runtime.NumCPU()) wg.Add(2) go a() go b()}06、
var a []intvar b chan int // 需要指定通道中元素的类型var wg sync.WaitGroup
func noBufChannel() { fmt.Println(b) // nil b = make(chan int) // 不带缓冲区通道的初始化 wg.Add(1) go func() { defer wg.Done() x := <-b fmt.Println("后台goroutine从通道b中取到了", x) }()
b <- 10 // hang住了 fmt.Println("10发送到通道b中了...") wg.Wait()}
func bufChannel() { fmt.Println(b) // nil b = make(chan int, 10) // 不带缓冲区通道的初始化 b <- 10 // hang住了 fmt.Println("10发送到通道b中了...") b <- 20 fmt.Println("20发送到通道b中了...") x := <-b fmt.Println("从通道b中取到了", x) close(b)}func main() { bufChannel()}07、
// channel练习// 1. 启动一个goroutine,生成100个数发送到ch1// 2. 启动一个goroutine,从ch1中取值,计算其平方放到ch2中// 3. 在main中 从ch2取值打印出来
var wg sync.WaitGroupvar once sync.Once
func f1(ch1 chan<- int) { defer wg.Done() for i := 0; i < 100; i++ { ch1 <- i } close(ch1)}
func f2(ch1 <-chan int, ch2 chan<- int) { defer wg.Done() for { x, ok := <-ch1 if !ok { break } ch2 <- x * x } once.Do(func() { close(ch2) }) // 确保某个操作只执行一次}
func main() { a := make(chan int, 100) b := make(chan int, 100) wg.Add(3) go f1(a) go f2(a, b) go f2(a, b) wg.Wait() for ret := range b { fmt.Println(ret) }}08、
// 关闭通道
func main() { ch1 := make(chan bool, 2) ch1 <- true ch1 <- true close(ch1) // for x := range ch1 { // fmt.Println(x) // } <-ch1 <-ch1 x, ok := <-ch1 fmt.Println(x, ok) x, ok = <-ch1 fmt.Println(x, ok) x, ok = <-ch1 fmt.Println(x, ok)}09、
func worker(id int, jobs <-chan int, results chan<- int) { for j := range jobs { fmt.Printf("worker:%d start job:%d\n", id, j) time.Sleep(time.Second) fmt.Printf("worker:%d end job:%d\n", id, j) results <- j * 2 }}
func main() { jobs := make(chan int, 100) results := make(chan int, 100) // 开启3个goroutine for w := 1; w <= 3; w++ { go worker(w, jobs, results) } // 5个任务 for j := 1; j <= 5; j++ { jobs <- j } close(jobs) // 输出结果 for a := 1; a <= 5; a++ { <-results }}10、
/*使用goroutine和channel实现一个计算int64随机数各位数和的程序。1. 开启一个goroutine循环生成int64类型的随机数,发送到jobChan2. 开启24个goroutine从jobChan中取出随机数计算各位数的和,将结果发送到resultChan3. 主goroutine从resultChan取出结果并打印到终端输出*/
// job ...type job struct { value int64}
// Result ...type result struct { job *job sum int64}
var jobChan = make(chan *job, 100)var resultChan = make(chan *result, 100)var wg sync.WaitGroup
func zhoulin(zl chan<- *job) { defer wg.Done() // 循环生成int64类型的随机数,发送到jobChan for { x := rand.Int63() newJob := &job{ value: x, } zl <- newJob time.Sleep(time.Millisecond * 500) }}
func baodelu(zl <-chan *job, resultChan chan<- *result) { defer wg.Done() // 从jobChan中取出随机数计算各位数的和,将结果发送到resultChan for { job := <-zl sum := int64(0) n := job.value for n > 0 { sum += n % 10 n = n / 10 } newResult := &result{ job: job, sum: sum, } resultChan <- newResult }}func main() { wg.Add(1) go zhoulin(jobChan) // 开启24个goroutine执行保德路 wg.Add(24) for i := 0; i < 24; i++ { go baodelu(jobChan, resultChan) } // 主goroutine从resultChan取出结果并打印到终端输出 for result := range resultChan { fmt.Printf("value:%d sum:%d\n", result.job.value, result.sum) } wg.Wait()}11、
// select
func main() { ch := make(chan int, 10) for i := 0; i < 10; i++ { select { case x := <-ch: fmt.Println(x) case ch <- i: } }
}12、ini_demo 配置文件解析
// ini配置文件解析器
// MysqlConfig MySQL配置结构体type MysqlConfig struct { Address string `ini:"address"` Port int `ini:"port"` Username string `ini:"username"` Password string `ini:"password"`}
// RedisConfig ...type RedisConfig struct { Host string `ini:"host"` Port int `ini:"port"` Password string `ini:"password"` Database int `ini:"database"` Test bool `ini:"test"`}
// Config ...type Config struct { MysqlConfig `ini:"mysql"` RedisConfig `ini:"redis"`}
// 尽量去掌握func loadIni(fileName string, data interface{}) (err error) { // 0. 参数的校验 // 0.1 传进来的data参数必须是指针类型(因为需要在函数中对其赋值) t := reflect.TypeOf(data) fmt.Println(t, t.Kind()) if t.Kind() != reflect.Ptr { err = errors.New("data param should be a pointer") // 新创建一个错误 return } // 0.2 传进来的data参数必须是结构体类型指针(因为配置文件中各种键值对需要赋值给结构体的字段) if t.Elem().Kind() != reflect.Struct { err = errors.New("data param should be a struct pointer") // 新创建一个错误 return } // 1. 读文件得到字节类型数据 b, err := ioutil.ReadFile(fileName) if err != nil { return } // string(b) // 将字节类型的文件内容转换成字符串 lineSlice := strings.Split(string(b), "\r\n") // fmt.Printf("%#v\n", lineSlice) // 2. 一行一行得读数据 var structName string for idx, line := range lineSlice { // 去掉字符串首尾的空格 line = strings.TrimSpace(line) // 如果是空行就跳过 if len(line) == 0 { continue } // 2.1 如果是注释就跳过 if strings.HasPrefix(line, ";") || strings.HasPrefix(line, "#") { continue } // 2.2 如果是[开头的就表示是节(section) if strings.HasPrefix(line, "[") { if line[0] != '[' || line[len(line)-1] != ']' { err = fmt.Errorf("line:%d syntax error", idx+1) return } // 把这一行首尾的[]去掉,取到中间的内容把首尾的空格去掉拿到内容 sectionName := strings.TrimSpace(line[1 : len(line)-1]) if len(sectionName) == 0 { err = fmt.Errorf("line:%d syntax error", idx+1) return } // 根据字符串sectionName去data里面根据反射找到对应的结构体 for i := 0; i < t.Elem().NumField(); i++ { field := t.Elem().Field(i) if sectionName == field.Tag.Get("ini") { // 说明找到了对应的嵌套结构体,把字段名记下来 structName = field.Name fmt.Printf("找到%s对应的嵌套结构体%s\n", sectionName, structName) } } } else { // 2.3 如果不是[开头就是=分割的键值对 // 1. 以等号分割这一行,等号左边是key,等号右边是value if strings.Index(line, "=") == -1 || strings.HasPrefix(line, "=") { err = fmt.Errorf("line:%d syntax error", idx+1) return } index := strings.Index(line, "=") key := strings.TrimSpace(line[:index]) value := strings.TrimSpace(line[index+1:]) // 2. 根据strucrName 去 data 里面把对应的嵌套结构体给取出来 v := reflect.ValueOf(data) sValue := v.Elem().FieldByName(structName) // 拿到嵌套结构体的值信息 sType := sValue.Type() // 拿到嵌套结构体的类型信息
if sType.Kind() != reflect.Struct { err = fmt.Errorf("data中的%s字段应该是一个结构体", structName) return } var fieldName string var fileType reflect.StructField // 3. 遍历嵌套结构体的每一个字段,判断tag是不是等于key for i := 0; i < sValue.NumField(); i++ { filed := sType.Field(i) // tag信息是存储在类型信息中的 if filed.Tag.Get("ini") == key { // 找到对应的字段 fieldName = filed.Name fileType = filed break } } // 4. 如果key = tag,给这个字段赋值 // 4.1 根据fieldName 去取出这个字段 if len(fieldName) == 0 { // 在结构体中找不到对应的字符 continue } fileObj := sValue.FieldByName(fieldName) // 4.2 对其赋值 fmt.Println(fieldName, fileType.Type.Kind()) switch fileType.Type.Kind() { case reflect.String: fileObj.SetString(value) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: var valueInt int64 valueInt, err = strconv.ParseInt(value, 10, 64) if err != nil { err = fmt.Errorf("line:%d value type error", idx+1) return } fileObj.SetInt(valueInt) case reflect.Bool: var valueBool bool valueBool, err = strconv.ParseBool(value) if err != nil { err = fmt.Errorf("line:%d value type error", idx+1) return } fileObj.SetBool(valueBool) case reflect.Float32, reflect.Float64: var valueFloat float64 valueFloat, err = strconv.ParseFloat(value, 64) if err != nil { err = fmt.Errorf("line:%d value type error", idx+1) return } fileObj.SetFloat(valueFloat) } } } return}
func main() { var cfg Config err := loadIni("./conf.ini", &cfg) if err != nil { fmt.Printf("load ini failed, err:%v\n", err) return } fmt.Printf("%#v\n", cfg)}conf.init 文件
; mysql config[mysql]address=10.20.30.40port=3306username=rootpassword=rootroot
# redis config; [; [ ][redis]; heihei; = hahahaxxx=host =11.22.33.44port=6379password=root123database=0test=false