go语言:没有class

发布时间 2023-07-08 17:02:53作者: 好人~

参考:视频链接

没有class

go语言没有class,但是可以将方法可以被关联到你声明的struct类型,如下介绍了如何将方法关联到类型和构造函数:

package main

import (
    "fmt"
)

// 矩形结构体
type Rectangle struct {
    Length int
    Width  int
}

// 计算矩形面积
func (r *Rectangle) Area() int { // 将方法Area()关联到Rectangle类型上。  // Area开头的大写代表方法是public
    return r.Length * r.Width
}

// 模拟构造函数
func New(Length, Width  int) Rectangle{ // 一般将new开头的函数当作类型的构造函数,当然也可以直接叫new
    return Rectangle{Length ,Width  }
}

func main() {
    r := Rectangle{4, 2}
    // 调用 Area() 方法,计算面积
    fmt.Println(r.Area())
}

指针

go指针与c++指针的区别:

  • 指针和普通变量访问数据成员和方法,都是使用".",而不是"->"
  • 使用指针作为方法的接收者,那么才能在方法中修改数据成员。

指针与接口:

package main

import(
        "fmt"
        "strings"
)

type talker interface {
        talk() string
}
func shout(t talker) {
        louder := strings.ToUpper(t.talk())
        fmt.Println(louder)
}
type martian struct{}
func (m martian) talk() string {
        return "nack nack "
}

type laser int

func(l *laser) talk() string{
  return strings.Repeat("pew", int(*l))
}


func main() {
        shout(martian{})
        shout(&martian{})
        
        pew := laser(2)
        shout(&pew)
        // shout(pew)  // 错误
}

指向laser类型的指针满足了接口的类型,laser的类型并不满足接口的类型,所以shout(pew)会出错。

goroutine与channel

goroutine:协程,并发执行的代码。

package main
​
import (  
    "fmt"
)
​
func hello() {  
    fmt.Println("Hello world goroutine")
}
func main() {  
    go hello() // 开启一个协程
    fmt.Println("main function")
}

channel:

ch := make(chan int) // ch 的类型是 chan int
ch <- x // 将x发送到通道中
x = <-ch // 将通道中的数据接收到x上
<-ch     // 丢弃通道中接收的东西

close(ch) // 关闭

接受时:等待另一个goroutine向通道中发送数据。
发送时:等待另一个goroutine将通道中的数据取走。

简单的channel实例:

package main
import (
  "fmt"
  "time"
)
func main() {
  c := make(chan int)
  for i:=0; i<5; i++ {
      go sleepyGopher(i, c)
  }
  for i:=0; i<5;i++ {
    gopherID := <-c    // 多个goroutine向通道中发送数据,每次接收一个
    fmt.Println( "gopher" ,gopherID," has finished sleeping")
  }
}
func sleepyGopher(id int, c chan int) {
  time.Sleep(3*time.Second)
  fmt.Println(" ..",id," snore ...")
  c<-id
}

结果是无序的输出:

 .. 0  snore ...
 .. 2  snore ...
gopher 0  has finished sleeping
 .. 3  snore ...
 .. 4  snore ...
gopher 2  has finished sleeping
gopher 3  has finished sleeping
gopher 4  has finished sleeping
 .. 1  snore ...
gopher 1  has finished sleeping

select与time.After:

package main
import (
  "fmt"
  "time"
)
func main() {
  c := make(chan int)
  fori:=0;i<5;i++ {
    go sleepyGopher(i, c)
  }
  timeout := time.After(2*time.Second) // timeout是通道,会在两秒以后向timeout中发送数据
  for i:=0;i<5;i++{
    select{ // 两秒以后timeout中将会有数据,程序就会return
    case gopherID :=<-c: // 所以只执行睡眠在两秒以内的goroutine
      fmt.Println("gopher ",gopherID, " has finished sleeping" )
    case <-timeout: 
      fmt.Println("my patience ran out")
      return 
    }
  }
}

func sleepyGopher(id int, c chan int) {
  time.Sleep( time.Duration( rand.Intn(4000))*time.Millisecond ) // 0~4秒的随机时间
  c <- id
}

C++协程一般指的是可以挂起和恢复的函数,go中通过goroutine执行并发代码,通过channel等待事件发送。