美文网首页go首页投稿(暂停使用,暂停投稿)
你可能不知道的关于golang 的10件事情

你可能不知道的关于golang 的10件事情

作者: kingeasternsun | 来源:发表于2017-07-06 14:58 被阅读0次

    英文原文

    匿名结构体

    最常见的匿名用法,不用单独定义一个结构体类型

        var config struct {
            APIKey      string
            OAuthConfig oauth.Config
        }
    
        config.APIKey = "BADC0C0A"
    
    

    匿名结构体定义时并初始化

        data := struct {
            Title string
            Users []*User
        }{
            title,
            users,
        }
        err := tmpl.Execute(w, data)
    

    匿名结构体slice定义并初始化

        var indexRuneTests = []struct {
            s    string
            rune rune
            out  int
        }{
            {"a A x", 'A', 2},
            {"some_text=some_value", '=', 9},
            {"☺a", 'a', 3},
            {"a☻☺b", '☺', 4},
        }
    

    嵌套互斥锁

        var hits struct {
            sync.Mutex
            n int
        }
    
        hits.Lock()
        hits.n++
        hits.Unlock()
    

    嵌套结构体

        type Item struct {
            Title string
            URL   string
        }
    
        type Response struct {
            Data struct {
                Children []struct {
                    Data Item
                }
            }
        }
    

    命令行 go doc

    在命令行中,可以通过go doc 查看包相关接口信息

    wdy@wdy:~/learn/program-learn/golang$ go doc sync
    package sync // import "sync"
    
    Package sync provides basic synchronization primitives such as mutual
    exclusion locks. Other than the Once and WaitGroup types, most are intended
    for use by low-level library routines. Higher-level synchronization is
    better done via channels and communication.
    
    Values containing the types defined in this package should not be copied.
    
    func NewCond(l Locker) *Cond
    type Cond struct { ... }
    type Locker interface { ... }
    type Mutex struct { ... }
    type Once struct { ... }
    type Pool struct { ... }
    type RWMutex struct { ... }
    type WaitGroup struct { ... }
    
    wdy@wdy:~/learn/program-learn/golang$ go doc sync Mutex
    type Mutex struct {
            // Has unexported fields.
    }
        A Mutex is a mutual exclusion lock. Mutexes can be created as part of other
        structures; the zero value for a Mutex is an unlocked mutex.
    
    
    func (m *Mutex) Lock()
    func (m *Mutex) Unlock()
    
    wdy@wdy:~/learn/program-learn/golang$ go doc sync.mutex.lock
    func (m *Mutex) Lock()
        Lock locks m. If the lock is already in use, the calling goroutine blocks
        until the mutex is available.
    

    另外还有一个厉害的工具 ,执行下面命令

    godoc -http :6061
    

    会打开一个网页如下:

    2017-07-11 19:16:11屏幕截图.png

    可以方便的查询各个package的相关知识。

    在同一个channel上进行读写操作

    battle是一个阻塞channel,当多个goroutine执行warrior的时候,最先执行到select的goroutine进入到

    case battle <- name:
    

    此时其他goroutine会阻塞在select上,name进入battle的瞬间,阻塞等待的goroutine的其中一个会进入到

    case opponent := <-battle:
    

    battle数据被读取后,阻塞等待的剩余的goroutine的其中一个会进入到

    case battle <- name:
    

    按照如上流程反复直到所有goroutine执行完毕。

    var battle = make(chan string)
    
    func warrior(name string, done chan struct{}) {
        select {
        case opponent := <-battle:
            fmt.Printf("%s beat %s\n", name, opponent)
        case battle <- name:
            // I lost :-(
        }
        done <- struct{}{}
    }
    
    func main() {
        done := make(chan struct{})
        langs := []string{"Go", "C", "C++", "Java", "Perl", "Python"}
        for _, l := range langs {
            go warrior(l, done)
        }
        for _ = range langs {
            <-done
        }
    }
    

    可以看到每次结果都是不一样的

    wdy@wdy:~/learn/program-learn/golang$ go run learnchannel.go
    Go beat Python
    C++ beat C
    Java beat Perl
    wdy@wdy:~/learn/program-learn/golang$ go run learnchannel.go
    Perl beat Java
    Python beat Go
    C beat C++
    wdy@wdy:~/learn/program-learn/golang$ go run learnchannel.go
    C++ beat C
    Java beat Perl
    Python beat Go
    wdy@wdy:~/learn/program-learn/golang$ go run learnchannel.go
    Go beat Python
    Perl beat Java
    C beat C++
    wdy@wdy:~/learn/program-learn/golang$ go run learnchannel.go
    Python beat Go
    C beat C++
    Java beat Perl
    wdy@wdy:~/learn/program-learn/golang$ go run learnchannel.go
    Go beat Python
    Perl beat Java
    C beat C++
    wdy@wdy:~/learn/program-learn/golang$ go run learnchannel.go
    Go beat Python
    C beat C++
    Java beat Perl
    

    利用close来向其他goroutine广播

    func waiter(i int, block, done chan struct{}) {
        time.Sleep(time.Duration(rand.Intn(3000)) * time.Millisecond)
        fmt.Println(i, "waiting...")
        <-block
        fmt.Println(i, "done!")
        done <- struct{}{}
    }
    
    func main() {
        block, done := make(chan struct{}), make(chan struct{})
        for i := 0; i < 4; i++ {
            go waiter(i, block, done)
        }
        time.Sleep(5 * time.Second)
        close(block)
        for i := 0; i < 4; i++ {
            <-done
        }
    }
    

    结果

    2 waiting...
    1 waiting...
    3 waiting...
    0 waiting...
    0 done!
    3 done!
    2 done!
    1 done!
    

    利用nil通道的特性

    goroutine对于值为nil的channel进行接受或发送操作时,会永久block

    type Work struct {
        Job string
    }
    
    func (w Work) Do() {
        fmt.Println("do", w.Job)
    }
    
    func (w Work) Refuse() {
        fmt.Println(w.Job + "stopped")
    }
    
    func makeWork(ch chan Work) {
        for {
            time.Sleep(500 * time.Millisecond)
            ch <- Work{Job: "job"}
        }
    }
    
    func worker(i int, ch chan Work, quit chan struct{}) {
        for {
            select {
            case w := <-ch:
                if quit == nil {
                    w.Refuse()
                    fmt.Println("worker", i, "refused", w)
                    break
                }
                w.Do()
                fmt.Println("worker", i, "processed", w)
            case <-quit:
                fmt.Println("worker", i, "quitting")
                quit = nil
            }
        }
    }
    

    结果

    do job
    worker 0 processed {job}
    do job
    worker 1 processed {job}
    do job
    worker 2 processed {job}
    do job
    worker 3 processed {job}
    do job
    worker 0 processed {job}
    do job
    worker 1 processed {job}
    do job
    worker 2 processed {job}
    do job
    worker 3 processed {job}
    do job
    worker 0 processed {job}
    worker 0 quitting
    worker 1 quitting
    worker 2 quitting
    worker 3 quitting
    jobstopped
    worker 0 refused {job}
    jobstopped
    worker 1 refused {job}
    jobstopped
    worker 2 refused {job}
    jobstopped
    worker 3 refused {job}
    

    后记

    之前一直在CSDN上写文章,后面会逐步转换到简书上,还请大家多多支持。

    相关文章

      网友评论

        本文标题:你可能不知道的关于golang 的10件事情

        本文链接:https://www.haomeiwen.com/subject/wsvhhxtx.html