2.4 面向对象编程
2.4.1匿名组合
type Person struct {
id int
name string
age int
}
type Student struct {
Person //只有类型 没有名字,匿名字段 继承了person的成员
garde string
class string
}
2.4.1.2 定义类,赋值,修改
//定义类
var per1 Student = Student{Person{1, "生活", 18}, "初中", "初一"}
fmt.Println("per1", per1)
//自动推导类型
per2 := Student{Person{1, "生活", 18}, "初中", "初一"}
fmt.Printf("per2 %v\n", per2)
//单独复制
per3 := Student{class: "初一"}
fmt.Printf("per3 %v\n", per3)
per4 := Student{Person: Person{id: 5}, class: "初一"}
per4.name = "sss"
per4.Person = Person{5, "aaa", 22}
fmt.Printf("per4 %v\n", per4)
2.4.1.3 匿名字段追加
//非结构匿名字段
type addColum string
func main() {
per2 := Student{Person{1, "生活", 18}, "初中", "初一", "追加字段"}
fmt.Printf("per2 %v\n", per2)//per2 {{1 生活 18} 初中 初一 追加字段}
}
2.4.1.4 地址匿名字段追加
//非结构匿名字段
type addColum string
type Person struct {
id int
name string
age int
}
type Student struct {
*Person //只有类型 没有名字,匿名字段 继承了person的成员
garde string
class string
addColum
}
func main() {
per2 := Student{&Person{1, "生活", 18}, "初中", "初一", "追加字段"}
fmt.Printf("per2 %v\n", per2)
fmt.Println(per2.id, per2.name, per2.age, per2.garde, per2.class)
var per3 Student
per3.Person = new(Person)
per3.addColum = "append"
per3.id = 5
per3.name = "sss"
fmt.Println(per3.id, per3.name, per3.age, per3.garde, per3.class)
}
2.4.2方法
2.4.2.1 定义
//面向对象,方法:给某个类型绑定一个函数
type long int
//tmp叫接受者,接受者传递的一个参数
func (tmp long) Add02(other long) long {
fmt.Println("tmp =", tmp)//1
return tmp + other
}
func main() {
//定义一个变量
var test long = 1
//调用方法格式 :变量名.函数
r := test.Add02(3)
fmt.Println("r =", r)//4
}
2.4.2.2 赋值,输出
//输出函数
func (per Person) pringInfo() {
fmt.Println("per =", per)
}
//赋值函数
func (per Person) setInfo(a int, b string, c int) {
per.id = a
per.name = b
per.age = c
fmt.Println("per =", per)
}
func main() {
per1 := Person{1, "小三", 20}
per1.pringInfo()
per1.setInfo(2, "小三的小三", 21)
}
2.4.2.3 值传递与引用传递
type Person struct {
id int
name string
age int
}
//赋值函数
func (per Person) setInfo(a int, b string, c int) {
per.id = a
per.name = b
per.age = c
fmt.Printf("per = %v\n", per)//per = {3 修改 22}
}
//引用传递
func (per *Person) setInfoPoint(a int, b string, c int) {
per.id = a
per.name = b
per.age = c
fmt.Printf("per = %v\n", per)//per = &{4 修改 32}
}
func main() {
per1 := Person{1, "小三", 20}
per1.setInfo(3, "修改", 22) //引用传递
fmt.Println(per1)//{1 小三 20}
per2 := Person{2, "小三的小三", 21}
per2.setInfoPoint(4, "修改", 32) //值传递
fmt.Println(per2) //{4 修改 32}
}
2.4.2.4 继承传递
type Person struct {
id int
name string
age int
}
type Student struct {
Person
garde string
}
//输出函数
func (per Person) pringInfo() {
fmt.Println("per =", per)
}
func main() {
//继承
stu := Student{Person{5, "小三5", 25}, "s"}
stu.pringInfo()
fmt.Println(stu)
}
2.4.2.5 方法值
stu := Student{Person{5, "小三5", 25}, "s"}
stu.pringInfo()
//方法值 保存方式入口地址
pFunc := stu.pringInfo //这个就是方法值,调用函数时,无需再传递接受者
pFunc() //等价于 stu.pringInfo()
2.4.2.5 方法表达式
//方法表达式
f := (*PePerson).setInfoPoint
f(&stu) //等价于 stu.setInfoPoint()
f1 := (PePerson).setInfo
f1(stu) //等价于 stu.setInfo()
fmt.Println(stu)
2.4.3接口
2.4.3.1 定义
//定义接口
type inter interface {
say()
}
//studnt实现了say方法
func (tmp *Teacher) say() {
fmt.Printf("Studnt %s\n", tmp.zz)
}
func main() {
var i inter
//只要实现 该接口,就可以给这个接口赋值
s := &Teacher{"是啥"}
i = s
i.say()//Studnt 是啥
}
2.4.3.2 继承实现
type inter interface {
say()
}
type inter1 interface {
inter
say1()
}
//studnt实现了say方法
func (tmp *Teacher) say() {
fmt.Printf("Studnt %s\n", tmp.zz)
}
//studnt实现了say1方法
func (tmp *Teacher) say1() {
fmt.Printf("Studnt %s\n", tmp.zz)
}
func main() {
var i inter1
//只要实现 该接口,就可以给这个接口赋值
s := &Teacher{"是啥"}
i = s
i.say()
i.say1()
}
2.4.3.3 接口转换
var i1 inter1 //超集
i1 = &Teacher{"是啥"}
var i inter //子集
i = i1 //可以 超集可以转换为子集
i.say()
2.4.3.4 空接口
i := make([]interface{}, 3)
i[0] = 1
i[1] = "ss"
for index, data := range i {
if value, ok := data.(int); ok == true {
fmt.Printf("index [%v] ,x[%d]\n", index, value)
}
}
2.5 异常处理,字符串
2.5.1错误接口(error)
err1 := fmt.Errorf("%s", "no error")
fmt.Println(err1)
err2 := errors.New("错误")
fmt.Println(err2)
2.5.1.1错误接口的应用
func MyDiv(a, b int) (result int, err error) {
err = nil
if b == 0 {
err = errors.New("B不能为0")
} else {
result = a / b
}
return
}
func main() {
val, err := MyDiv(1, 0)
if err != nil {
fmt.Println(err)
} else {
fmt.Println(val)
}
}
2.5.2函数程序中断(panic)
func test() {
//导致程序中断
panic("this is a panic")
}
2.5.3函数程序(recover)
func test1() {
defer func() {
//err是该函数默认返回值
if err := recover(); err != nil {
fmt.Println(err)
}
}() //()调用此函数
}
2.5.4字符串函数的使用
fmt.Println(strings.Contains("abcdefg", "abc")) //true
arr := []string{"abc", "hello", "arr"}
fmt.Println(strings.Join(arr, "@")) //abc@hello@arr
fmt.Println(strings.Index("abcdefg", "b")) //1
arrStr := "abc@hello@arr"
fmt.Println(strings.Split(arrStr, "@")) //[abc hello arr]
2.5.5 strconv包
arr1 := make([]byte, 0, 1024)
arr1 = strconv.AppendBool(arr1, true)
//整数转字符串
arr2 := strconv.Itoa(6666)
fmt.Println(arr2)
//其他类型转换为字符串
var str string
str = strconv.FormatBool(false)
fmt.Println(str)
2.6 json
2.6.1 结构体转json
import "fmt"
import "encoding/json"
//首字母必须大写
type Student struct {
Id int `json:"-"` //此字段不会输出
Name string `json:"name"` //返回时返回指定字段
Sub []string
IsOk bool `json:",string"` //返回字符串
Price float64
}
func main() {
stu := Student{1, "小明", []string{"go", "java", "php"}, true, 50.00}
fmt.Println(stu)
//json转义
buf, err := json.Marshal(stu)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(buf) //[123 34 73 100 34 58 49 44 34 78 97 109 101 34 58 34 229 176 143 230 152 142 34 44 34 83 117 98 34 58 91 34 103 111 34 44 34 106 97 118 97 34 44 34 112 104 112 34 93 44 34 73 115 79 107 34 58 116 114 117 101 44 34 80 114 105 99 101 34 58 53 48 125]
fmt.Println(string(buf))
}
2.6.2 map转json
map1 := make(map[string]interface{}, 4)
map1["id"] = 5
map1["name"] = "实时"
buf, err := json.MarshalIndent(map1, "", " ")
fmt.Println(string(buf))
fmt.Println(err)
2.6.3 json转实体
func main() {
jsonBuf := `
{
"id": 5,
"name": "实时"
}`
var stu1 Student
json.Unmarshal([]byte(jsonBuf), &stu1)
fmt.Println(stu1)//{0 实时 [] false 0}
}
2.6.4 json转map
func main() {
jsonBuf := `
{
"id": 5,
"name": "实时"
}`
map2 := make(map[string]interface{}, 4)
json.Unmarshal([]byte(jsonBuf), &map2)
fmt.Println(map2)
//断言 判断类型
var str string
for key, value := range map2 {
switch data := value.(type) {
case string:
str = data
fmt.Printf("map[%s]的值类型为string", key)
case []interface{}:
fmt.Printf("map[%s]interface{}", key)
}
}
}
2.7 goroutine并发并行
2.7.1 demo
import "fmt"
import "time"
func newWork() {
for {
fmt.Println("this is newWork")
time.Sleep(1000)
}
}
func main() {
//设置并行处理器
num := runtime.GOMAXPROCS(1)
fmt.Println(num)
//goroutine
go newWork() //新建一个协程任务
for {
fmt.Println("this is mainWork")
time.Sleep(1000)
}
}
2.7.2主协程退出,子协程也退出
func main() {
//主协程退出了,其它子协程也要跟着退出
go func() {
for {
fmt.Println("this is goroutine")
}
}()
i := 0
for {
i++
fmt.Println("this is mainFor")
time.Sleep(1000)
if i > 2 {
break
}
}
}
2.7.3 Goschedr让出调度资源 Goexit 终止
import "runtime"
func main() {
//设置并行处理器
num := runtime.GOMAXPROCS(1)
fmt.Println(num)
//Goschedr
go func() {
for j := 0; j < 2; j++ {
fmt.Println("this is goroutine")
runtime.Goexit() //终止所有协程
}
}()
i := 0
for {
i++
fmt.Println("this is mainFor")
runtime.Gosched() //让出时间片,先让其他协议执行
if i > 2 {
break
}
}
}
2.7.4
2.7.4.1 Demo channel管道
//创建一个无缓存的channel
var ch = make(chan int)
func printWork(val string) {
fmt.Println(val)
fmt.Println(val)
fmt.Println(val)
fmt.Println(val)
fmt.Println(val)
}
func per(sendv string) {
printWork(sendv)
ch <- 666 //给管道协数据,发送
}
func per1(sendv string) {
<-ch //从管道取数据,接收,如果管道没有数据阻塞
printWork(sendv)
}
func main() {
go per("per1")
go per("per2")
for {
}
// per2
// per2
// per2
// per2
// per1
// per1
// per1
}
2.7.4.2 channel 特点
func main() {
var ch3 chan<- float64 //ch3是单向channel 只用于读写float64数据
ch := make(chan int)
//双向隐转单向
var writhCh chan<- int = ch //只能写,不能读
var readCh <-chan int = ch //只能读,不能写
writh <-666 //写
<-readch//读
//单向无法转换为双向
var ch2 chan int = writhCh
}
2.7.4.3 channel 应用
//生产者 只能写,不能读
func product(out chan<- int) {
for i := 0; i < 10; i++ {
out <- i * i
}
close(out)
}
//消费者 只能读,不能写
func consumer(in <-chan int) {
for num := range in {
fmt.Println("consumer=", num)
}
}
func main() {
//创建一个双向通道
ch := make(chan int)
//生产者
go product(ch)
//消费者
consumer(ch)
}
2.7.4.4 定时器
import "time"
func main() {
//只执行一次
timer := time.NewTimer(2 * time.Second)
//重复执行
timer1 :=time.NewTicker(2 * time.Second)
fmt.Println(time.Now())
t := <-timer.C
fmt.Println(t)
timer.Reset(1 * time.Second) //重新设置
timer.Stop() //定时器停止
//2020-06-13 14:06:05.8875131 +0800 CST m=+0.008002001
//2020-06-13 14:06:07.8881753 +0800 CST m=+2.008664201
}
2.7.4.5 select用法
func main() {
ch := make(chan int)
quit := make(chan bool)
//新开一个协程
//读数据
go func() {
for {
select {
case num := <-ch:
fmt.Println("num = ", num)
case <-time.After(3 * time.Second):
fmt.Println("超时")
quit <- true
}
}
}() //自调用
//写数据
for i := 0; i < 5; i++ {
ch <- i
time.Sleep(time.Second)
}
<-quit
fmt.Println("程序结束")
}