Go语言基础2

方法和接收者

  • 方法定义

    • 方法是一种作用于特定类型变量的函数,这种特定类型变量叫做接收者(Receiver),接收者的概念类似于其他语言中的this或者self

//方法的定义实例
//定义结构体
type Person struct{
    name string
    age int8
}
func NewPerson(name string, age int8)*Person{
    return &Person{
        name: name,
        age:age,
    }
}
//方法  Dream是为Person类型定义方法
func (p Person) Dream(){
    fmt.Printf("%s\n", p.name)
}
func main() {
    a := NewPerson("fdfv", int8(19))
    (*a).Dream()
    a.Dream()
}
  • 接收者

    //方法的定义实例
    //定义结构体
    type Person struct{
        name string
        age int8
    }
    func NewPerson(name string, age int8)*Person{
        return &Person{
            name: name,
            age:age,
        }
    }
    //方法  Dream是为Person类型定义方法
    func (p Person) Dream(){
        fmt.Printf("%s\n", p.name)
    }
    //接收者类型是指针
    func (p *Person) SetAge(newAge int8){
        p.age = newAge
    }
    //值接收者 修改值不会改变
    func (p Person) SetAge1(newAge int8){
        p.age = newAge
    }
    func main() {
        a := NewPerson("fdfv", int8(19))
        (*a).Dream()
        a.Dream()
        fmt.Println(a.age)
        a.SetAge(int8(23))
        fmt.Println(a.age)
    }
  • 指针类型使用场合

    • 需要修改接收者中的值

    • 接收者是拷贝代价比较大的对象

    • 保证一致性,如果有某个方法使用了指针接收者,那么其他方法也应该

结构体字段可见性和JSON序列化

如果一个go语言中定义的标识符是首字母大写的,那么就是对外可见的

  • 一个文件夹下面只能有一个包,同样一个包的文件不能在多个文件夹下

  • 包名可以不和文件夹的名字一样

  • 匿名导包 import _"包的路径"

  • init() 函数没有参数和返回值,在包导入的时候自动执行,执行顺序:先全局声明->init()->main()

  • 不允许导入包而不使用,不允许循环引用包

接口

  • 定义:是一种类型,是一种抽象的类型

    //接口
    type dog struct {
    }
    func (d dog) say(){
        fmt.Println("wangwang")
    }
    type cat struct {
    }
    func (c cat) say(){
        fmt.Println("miaomiao")
    }
    //接口不管你是什么类型,它只管你要实现什么方法
    //定义一个类型,一个抽象类型,只要实现了say()这个方法的类型都可以称为sayer类型
    type sayer interface {
        say()
    }
    //不管传进来的什么类型,它只管你要实现什么方法
    func do(arg sayer){
        arg.say()
    }
    func main() {
        d := dog{}
        do(d)
        c := cat{}
        do(c)
    }

    使用指针接收者实现接口:只有类型指针能够保存到接口变量中

    同一类型可以实现多个接口,不同类型可以实现同一接口

空接口

//空接口
//接口中没有定义任何需要实现的方法时,该接口就是一个空接口
//任意类型都实现了空接口-->空接口变量可以储存任意值
type xxx interface {
​
}
//空接口的应用
//作为函数的参数
//可以作为map的value
func main() {
    var x interface{}
    x = "hello"
    //fmt.Println(x)
    x = 100
    //fmt.Println(x)
    
    ret, ok := x.(string)
    if !ok{
        fmt.Println("fss")
    }else{
        fmt.Println("fv", ret)
    }
}

反射

定义

  • 是指在程序运行期本身进行访问和修改的能力

  • reflect包

    package main
    ​
    import (
        "fmt"
        "reflect"
    )
    ​
    func reflectType(x interface{}){
        //不知道传来的变量是什么类型
        //通过类型断言
        //借助反射
         obj := reflect.TypeOf(x)
         fmt.Println(obj, obj.Name(), obj.Kind())
         fmt.Printf("%T\n", obj)
    }
    ​
    func main() {
        var a float32 = 1.234
        reflectType(a)
    }

并发编程

并发与并行

  • goroutine->线程

    func main() { //开启一个主goroutine去执行main函数
    ​
        wg.Add(10000)
        for i := 0;i < 10000;i++{
            go func(i int){
                fmt.Println("hello", i)
                wg.Done()
            }(i)
        }//开启了一个goroutine去执行hello这个数
        fmt.Println("hello main")
        //time.Sleep(time.Second)
        wg.Wait()//等待所有小弟执行完
    }
  • GOMAXPROCS

    通过runtime.GOMAXPORCS函数设置当前程序开发时占用的CPU逻辑核心数

  • go语言中操作系统线程和goroutine的关系

    • 一个操作系统线程对应用户态多个goroutine

    • go程序可以同时使用多个操作系统线程

    • goroutine和OS线程时多对多的关系

  • channel 就是goroutine之间的连接,channel是可以让一个goroutine发送特定值到另一个goroutine的通信机制

    • channel是一种特殊的类型,像一个传送带或者队列,遵循先进先出的规则

    • 通道有发送、接受、和关闭三种操作

      func worker(id int,jobs <- chan int, results chan <- int){
          for job := range jobs{
              fmt.Printf("worker:%d start job:%d\n", id, job)
              results <- job*2
              time.Sleep(time.Millisecond*500)
              fmt.Printf("worker:%d start job:%d\n", id, job)
          }
      }
      func main(){
          //var ch1 chan int //需要初始化之后才能使用
          //ch1 = make(chan int, 1)
          //ch1 <- 10
          //x := <- ch1
          //fmt.Println(x)
          //close(ch1)
          jobs := make(chan int, 100)
          results := make(chan int, 100)
          //开启三个goroutine
          for i := 0;i < 3;i++{
              go worker(i, jobs, results)
          }
          //发送5个任务
          for i := 0; i < 5; i++{
              jobs <- i
          }
          close(jobs)
          for i := 0; i < 5; i++{
              ret := <- results
              fmt.Println(ret)
          }
      }
  • select的使用

    select {
            case <- ch1:
                ...
            case data := <- ch2:
                ...
        default:
            //默认操作
        }

    类似于switch语句,每个擦色会对应于一个通道的通信过程,使用select语句能提高代码可读性

并发同步和锁

/*互斥锁能够保证同一时间有且只有一个线程进入临界区,其他的线程则在等待锁;
当互斥锁释放后,等待的线程才能进入临界区
*/
var(
    x int64
    wg sync.WaitGroup
    lock sync.Mutex
)
​
func add(){
    for i := 0;i < 5000;i++{
        lock.Lock()
        x = x+1
        lock.Unlock()
    }
    wg.Done()
}
​
func main(){
    wg.Add(2)
    go add()
    go add()
    wg.Wait()
    fmt.Println(x)
}

读写锁分为两种:读锁和写锁

读锁:当一个线程获取读锁之后,其他的线程如果是获取读锁则继续获取,获取写锁则会等待

写锁:当一个线程获取写锁之后,其他的线程无论是获取读锁还是写锁都会等待

读写锁非常适合读多写少的场景

网络编程

互联网分层

  • 应用层,传输层,网络层,数据链路层,物理层

TCP通信

  • TCP协议和TCP服务端

  • TCP服务端处理流程

    1. 监听端口

    2. 接受客户端请求建立链接

    3. 创建goroutine处理机制

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值