2020年7月

package main

import "fmt"

func main() {
    var f func()

    var a *struct{}

    list := []interface{}{f, a}

    for _, item := range list {
        if item == nil {
            fmt.Println("nil")
        }
    }
}

我们来看上面的代码,我们的第一反应应该是输出两个 nil,但事实上并非如此。我们来在 for 循环中输出 item。

    ...
    for _, item := range list {
    fmt.Println(item)
        if item == nil {
            fmt.Println("nil")
        }
    }
    ...

 title=

item 的两个输出的确是 nil ,因为我们只是定义了两个变量却没有对变量进行复制,所以他的值肯定就是 nil,但是为什么在判断的时候确认为他们不是 nil 呢?

首先,我们要知道 fmt.Println 打印数据的时候是打印出变量的值,也就是相当于 fmt.Printlf("%v\n" ,item) ,但是 item 其实是有类型的,我们先修改一下代码。

package main

import "fmt"

func main() {
    //var f func()

    var a *struct{}

    list := []*struct{}{a}

    for _, item := range list {
        if item == nil {
            fmt.Println("nil")
        }
    }
}

//output: nil

当我们将 list 的类型修改为 []*struct{} 的时候就可以正确判断了,那么就说明是由于 interface 导致的判断出错。

我们在对 interface 进行 != nil 判断的时候,必须值和类型都为 nil 的时候才可以,我们可以通过 reflect 反射包来判断 一个 interface 的值是否为 nil.

package main

import (
    "fmt"
    "reflect"
)

func main() {
    //var f func()

    var a *struct{}

    list := []*struct{}{a}

    for _, item := range list {
        if  reflect.ValueOf(item).IsNil() {
            fmt.Println("nil")
        }
    }
}

请求时间过长,用户侧可能已经离开本页面了,服务端还在消耗资源处理,得到的结果没有意义,同时过长时间的服务端处理会占用过多资源,导致并发能力下降,甚至出现不可用事故,一般一个请求是由多个串行或并行的子任务来完成的,每个子任务可能是另外的内部请求,那么当这个请求超时的时候,我们就需要快速返回,释放占用的资源,比如goroutine,文件描述符等。

我们可以利用管道了来决这个问题。

package main

import (
    "fmt"
    "sync"
    "time"
)
package main

import (
    "fmt"
    "time"
)

func job(ch chan<- struct{}) {
    time.Sleep(time.Second * 5)
    ch <- struct{}{}
}

var ch chan struct{}

func main() {
    ch = make(chan struct{}, 1)
    go func() {
        job(ch)
    }()

    select {
    case <-ch:
        fmt.Println("done")
    case <-time.After(time.Second * 3):
        fmt.Println("timeout process exit!")
    }

}