GO语言学习之路23

2022/02/14   今天又是不熬夜的一天,舒服~
package main

import (
	"fmt"
	"time"
)

func main() {
	//管道可以声明为只读或者只写

	//1.在默认情况下,管道是双向的
	//var chan1 chan int	//可读可写

	//2.声明为只写
	var chan2 chan<- int
	chan2 = make(chan int, 3)
	chan2 <- 20

	//3.声明为只读
	var chan3 <-chan int
	chan3 = make(<-chan int, 2)
	num2 := <-chan3
	fmt.Println("num2", num2)

	/*
		可以通过函数传参把双向管道传入实参,
		函数可以用可读或可写管道接收,防止误操作
	*/

	//*********使用select可以解决从管道取数据的阻塞问题
	intChan := make(chan int, 10)
	for i := 0; i < 10; i++ {
		intChan <- i
	}
	stringChan := make(chan string, 5)
	for i := 0; i < 5; i++ {
		stringChan <- "hello" + fmt.Sprintf("%d", i)
	}
	/*
		传统的方法在遍历管道时,如果不关闭会阻塞导致 deadlock
		在实际开发中,可能不好确定声明时候关闭管道
		可以使用select方式解决
	*/
label:
	for {
		select {
		//如果这里intChan一直没有关闭,不会一直阻塞而deadlock
		case v := <-intChan:
			fmt.Println("从intChan读取了数据\n", v)
			time.Sleep(time.Second)
		case v := <-stringChan:
			fmt.Println("从stringChan读取了数据\n", v)
			time.Sleep(time.Second)
		default:
			fmt.Println("都读取不到了,溜了")
			time.Sleep(time.Second)
			break label
		}
	}
}
package main

import (
	"fmt"
	"time"
)

func sayHello() {
	for i := 0; i < 10; i++ {
		time.Sleep(time.Second)
		fmt.Println("hello world")
	}
}

func test() {
	/*
		panic: assignment to entry in nil map
		这里会报panic,原因是没有给map make空间
		主线程中启动两个协程,这个协程panic导致整个程序崩溃,如果希望
		test()协程不影响到其他协程的运行,可以用 defer + recover

	*/
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("test()发生错误", err)
			//这里可以用发邮件或者其他提示开发人员有错误出现
			//不会影响到其他协程,只会终止本协程
		}
	}()
	var myMap map[int]string
	myMap[0] = "hello"
}

func main() {
	go sayHello()
	go test()
	for i := 0; i < 10; i++ {
		fmt.Println("主线程")
		time.Sleep(time.Second)
	}
}
package main

import (
	"fmt"
	"reflect"
)

/*
	反射要注意的细节

	1.reflect.Value.Kind 获取变量的类别,返回的是一个常量(看手册)

*/

/*
	编写一个案例,
	演示对基本数据类型,interface{}, reflect.Value进行反射的基本操作
*/

//专门演示反射
func reflectTest01(b interface{}) {
	//通过反射获取传入的变量的type-类型,  kind-类别, 值
	//1.先获取到reflect.Type
	rType := reflect.TypeOf(b)
	fmt.Println("rType = ", rType) //rType =  int

	//2.获取到reflect.Value
	rValue := reflect.ValueOf(b)
	fmt.Println("rValue = ", rValue) //rValue =  100
	/*这里需要注意这个100不是num的100,而是反射的value值*/

	//获取变量的kind  //两种方法取出来的是一样的
	fmt.Println("rType kind = ", rType.Kind())   //rType kind =  int
	fmt.Println("rValue kind = ", rValue.Kind()) //rValue kind =  int

	n1 := 10
	n2 := 2 + n1
	fmt.Println("n2 = ", n2)
	//n3 := 2 + rValue //cannot convert 2 (untyped int constant) to struct{reflect.flag}
	/*  */
	fmt.Printf("rValue = %v, rValue type = %T\n", rValue, rValue)
	/*rValue = 100, rValue type = reflect.Value*/

	/*通过方法可以获取出 rValue 的值*/
	n4 := 2 + rValue.Int() //放入的是int值,可以直接用方法,其他的类型也有方法
	fmt.Println("n4 = ", n4)

	//如果要把 rValue重新转换成interface{},用断言,再转换成int
	num5 := rValue.Interface()
	num6 := num5.(int)
	fmt.Println("num6 = ", num6)

}

func main() { //对变量的反射

	var num int = 100
	reflectTest01(num)
}

 

 

package main

import (
	"fmt"
	"reflect"
)

type Student struct {
	Name string
	Age  int
}

func reflectTest02(stu interface{}) {
	//1.先获取到reflect.Type
	rType := reflect.TypeOf(stu)
	fmt.Println("rType = ", rType) //rType =  main.Student

	//2.获取到reflect.Value
	rValue := reflect.ValueOf(stu)
	fmt.Println("rValue = ", rValue) //rValue =  {levi 18}

	//3.将rValue抓成 interface{}
	iV := rValue.Interface()
	fmt.Printf("iV = %v, iV Type = %T\n", iV, iV) //iV = {levi 18}, iV Type = main.Student

	//4.我们要把接口断言转成需要的类型才能取出结构体中的数据
	/*  可以用switch更加灵活
	switch iV.(type) {
	case Student:
		fmt.Println("断言为Student结构体")
	}
	*/
	myStu, ok := iV.(Student)
	if ok {
		fmt.Println("stu.Name = ", myStu.Name)
	}

}

func main() { //对结构体的反射
	stu := Student{"levi", 18}
	reflectTest02(stu)
}

 

package main

import "fmt"

/*
	常量介绍
	1.常量使用const修饰
	2.常量在定义的时候,必须初始化
	3.常量不能修改
	4.常量只能修饰bool,数值类型(int,float系列),string类型
	5.语法:const identifier [type] = value
	6.常量也是通过首字母的大小写来控制访问范围
*/

func main() {
	//1.2
	const tax int = 0

	//3.error
	//tax = 10//cannot assign to tax (constant 0 of type int)

	const name = "levi"
	const t float64 = 0.8
	//const a int //err
	const q = 9 / 3 //  9/3是常量值,没问题

	//num := 2
	//const c = 8 / num //err,编译器认为num是变量,
	//num是不确定的可变的,但是c又是不可变的

	//比较简洁的写法
	const (
		a = 1
		b = 2
	)

	//还有一种专业的写法,像枚举
	const (
		p = iota // p默认为0
		o
		i
		u
	)
	fmt.Printf("p = %d, o = %d, i= %d, u = %d\n", p, o, i, u)
	//p = 0, o = 1, i= 2, u = 3
	const (
		p1     = iota // iota默认为0
		o1     = iota
		i1, u1 = iota, iota
	)
	fmt.Printf("p1 = %d, o1 = %d, i1 = %d, u1 = %d\n", p1, o1, i1, u1)
	//p1 = 0, o1 = 1, i1 = 2, u1 = 2
	// iota 默认是0 换行会+1, 在一行里面值不会变
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值