zoukankan      html  css  js  c++  java
  • Go语言学习

    4.7 出让时间片

    我们可以在每个goroutine中控制何时主动出让时间片给其他goroutine,这可以使用runtime
    包中的Gosched()函数实现。
    实际上,如果要比较精细地控制goroutine的行为,就必须比较深入地了解Go语言开发包中
    runtime包所提供的具体功能。

    4.8.1 同步锁

    Go语言包中的sync包提供了两种锁类型:sync.Mutex和sync.RWMutex。Mutex是最简单
    的一种锁类型,同时也比较暴力,当一个goroutine获得了Mutex后,其他goroutine就只能乖乖等
    到这个goroutine释放该Mutex。RWMutex相对友好些,是经典的单写多读模型。在读锁占用的情
    况下,会阻止写,但不阻止读,也就是多个goroutine可同时获取读锁(调用RLock()方法;而写
    锁(调用Lock()方法)会阻止任何其他goroutine(无论读和写)进来,整个锁相当于由该goroutine
    独占。

    4.8.2 全局唯一性操作

    对于从全局的角度只需要运行一次的代码,比如全局初始化操作,Go语言提供了一个Once
    类型来保证全局的唯一性操作,具体代码如下:
    var a string
    var once sync.Once
    func setup() {
    a = "hello, world"
    }
    func doprint() {
    once.Do(setup)
    print(a)
    }
    func twoprint() {
    go doprint()
    go doprint()
    }
    如果这段代码没有引入Once,setup()将会被每一个goroutine先调用一次,这至少对于这个
    例子是多余的。在现实中,我们也经常会遇到这样的情况。Go语言标准库为我们引入了Once类
    型以解决这个问题。once的Do()方法可以保证在全局范围内只调用指定的函数一次(这里指
    setup()函数),而且所有其他goroutine在调用到此语句时,将会先被阻塞,直至全局唯一的
    once.Do()调用结束后才继续。

    tcp网络编程

    package main
    import (
      "net"
      "os"
      "bytes"
      "fmt"
    )
    func main() {
      if len(os.Args) != 2 {
        fmt.Fprintf(os.Stderr, "Usage: %s host:port", os.Args[0])
        os.Exit(1)
      }
      service := os.Args[1]
      conn, err := net.Dial("tcp", service)
      checkError(err)
      _, err = conn.Write([]byte("HEAD / HTTP/1.0 "))
      checkError(err)
      result, err := readFully(conn)
      checkError(err)
      fmt.Println(string(result))
      os.Exit(0)
    }

    func main() {
      if len(os.Args) != 2 {
        fmt.Fprintf(os.Stderr, "Usage: %s host:port", os.Args[0])
        os.Exit(1)
      }
      service := os.Args[1]
      tcpAddr, err := net.ResolveTCPAddr("tcp4", service)
      checkError(err)
      conn, err := net.DialTCP("tcp", nil, tcpAddr)
      checkError(err)
      _, err = conn.Write([]byte("HEAD / HTTP/1.0 "))
      checkError(err)
      result, err := ioutil.ReadAll(conn)
      checkError(err)
      fmt.Println(string(result))
      os.Exit(0)
    }
    func checkError(err error) {
    if err != nil {
    fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
    os.Exit(1)
    }
    }
    与之前使用Dail()的例子相比,这里有两个不同:
     net.ResolveTCPAddr(),用于解析地址和端口号;
     net.DialTCP(),用于建立链接。
    这两个函数在Dial()中都得到了封装。

    8.3 Vim配置
    Go语言安装包中已经包含了对Vim的环境支持。要将Vim配置为适合作为Go语言的开发环
    境,我们只需要按$GOROOT/misc/vim中的说明文档做以下设置即可。
    创建一个shell脚本govim.sh,该脚本的内容如下:
    mkdir -p $HOME/.vim/ftdetect
    mkdir -p $HOME/.vim/syntax
    mkdir -p $HOME/.vim/autoload/go
    ln -s $GOROOT/misc/vim/ftdetect/gofiletype.vim $HOME/.vim/ftdetect/
    ln -s $GOROOT/misc/vim/syntax/go.vim $HOME/.vim/syntax
    ln -s $GOROOT/misc/vim/autoload/go/complete.vim $HOME/.vim/autoload/go
    echo "syntax on" >> $HOME/.vimrc
    在执行该脚本之前,先确认GOROOT环境变量是否正确设置并已经起作用,具体代码如下:
    $ echo $GOROOT
    /usr/local/go
    如果上面这个命令的输出为空,则表示GOROOT尚未正确设置,请保证GOROOT环境变量正确
    设置后再执行上面的govim.sh脚本。
    现在可以执行这个脚本了,该脚本只需要执行一次。执行成功的话,在$HOME目录下将会
    创建一个.vim目录。之后再用Vim打开一个go文件,读者应该就可以看到针对Go语言的语法高亮
    效果了。
    Vim还可以配合gocode支持输入提示功能。接下来我们简单地配置一下。
    首先获取gocode:
    $ go get -u github.com/nsf/gocode
    这个命令会下载gocode相应内容到Go的安装目录去(比如/usr/local/go),因此需要保证有目录的
    写权限。然后开始配置gocode:
    $ cd /usr/local/go/src/pkg/github.com/nsf/gocode/
    $ cd vim
    $ ./update.bash
    配置就是这么简单。现在使用以下Vim的语法提示效果。用Vim创建一个新的Go文件(比如
    命名为auto.go),输入以下内容:
    package main
    import "fmt"
    func main() {
    fmt.Print
    请将光标停在fmt.Print后面,然后按组合键Ctrl+X+O(三个键同时按住后放开),你会看
    到fmt包里的所有3个以Print开头的全局函数都被列了出来:Print、Printf和Println。之
    后就可以用上下方向键选取,按回车键即可完成输入,非常方便。
    gocode其实是一个独立地提供输入提示的服务器程序,并非专为Vim打造。比如Emacs也
    可以很容易地添加基于gocode的Go语言输入提示功能。大家可以查看gocode的Github主页上
    的提示。

  • 相关阅读:
    HTTP 无法注册URL 进程不具有命名空间的访问权限
    逆变与协变详解
    正式学习React(五) react-redux源码分析
    正式学习React(四) ----Redux源码分析
    正式学习react(二)
    工作总结
    如何自定义echarts 线性图的选择事件
    viewport大白话
    关于div可编辑的复制粘贴问题
    nginx学习
  • 原文地址:https://www.cnblogs.com/ghost240/p/3214710.html
Copyright © 2011-2022 走看看