Golang 中国
回复了 cumt_21g 创建的主题: 妈蛋,整个go社区就没有一个正常的日志库? 2017-11-29 14:07

可以试试 gloglog15,前者是 Google 自己的,感觉这两个用着还可以,我也不是太喜欢 logrus

回复了 9096312 创建的主题: Go的接口怎么那么难理解呢? 2017-08-28 11:53

@aaaaaaaa 关于 init 的顺序性问题,不能算是个坑,因为官方文档以及语言规范中都已经说明了:一个包中的多个 init 是无序调用的,使用者不能假定其调用顺序。

再说,就算 Go 想有序,但它也不知道哪个先、哪个后呀,除非修改 init 的接口,以此来表明其先后顺序,但这违反了 Go 1 的兼容性规范,除非在 Go 2 中实现。但觉得这没太大的必要,而且反而增加了复杂度和理解度。

回复了 spidergo 创建的主题: 怎么限制goroutine数量 2017-07-07 10:02

自已写一个 Goroutine Pool,比如:https://gowalker.org/github.com/xgfone/go-tools/pools#GoPool 。大致思路是:写一个计数器,当启动一个 Goroutine 时,加 1,当 Goroutine 结束时,减 1。

另一个方法是:写一个 Goroutine 任务池(可以设置大小),把每个任务都放到一个管道 Channel 中,而任务池中的 Goroutine 会从管道 Channel 中取任务并处理。参见实现:https://gowalker.org/github.com/xgfone/go-tools/worker#Dispatcher

回复了 sax1412 创建的主题: mysql: too many connects 2017-06-23 10:24

xorm 有这两个接口,可以设置最大连接数。xorm也不错。其实我也挺喜欢gorm的,但它有个不好的缺点:只是一味地开发,不喜欢发布版本或打 Tag。这会对使用者造成很大的问题:今天能编译,到了明天可能就无法编译了。

回复了 sax1412 创建的主题: mysql: too many connects 2017-06-17 20:34

gorm底层使用了标准库database/sql,而sql有两个接口:SetMaxIdleConnsSetMaxOpenConns。其中,SetMaxOpenConns可以满足你的需求,但gorm中好像并没有与此接口对接(注:也可能作者已经实现了,但我没有发现此接口),以便允许使用者自定义最大连接数。sql默认情况下,连接数无限制。

你可以到 https://github.com/jinzhu/gorm/issues 上去提个 issue,请作者为gorm添加SetMaxOpenConns,以便用户可以自定义最大连接数。

回复了 TinKong 创建的主题: go性能有重大缺陷??????? 2016-11-30 14:18

@dxhdxh2k 这跟我当时的需求场景有关。

我先前曾有这个测试需求:在云平台上的云主机,当配置不足以承担服务需求时,可以热升级 CPU内存,而升级后,新增的 CPU内存 是否会立即被投入使用。

所以,我需要:(1)跑满所有 CPU,(2)将内存使用完,并还要再使用一部分 SWAP 分区中的内存。这样,当从低配置升级到高配置时,我可以清晰的看到新增的 CPU 被立即使用了,而 SWAP 分区中的内存也被移到了新增的内存中。

因此,我需要分配大量的内存。放在循环内,可以循环分配。在 64 位系统上,最终可以分配大约 2~3GB 的内存。

PS:我当时测试的 Case 是,从 1核1GB 升级到 2核4GB,因此,程序使用的CPU核为 2,内存分配了 2GB 多。

回复了 TinKong 创建的主题: go性能有重大缺陷??????? 2016-11-25 11:16

测试:

  • CPUMem:2核4GB
  • OS: CentOS 7.2 终端界面
  • GO: Go 1.7.3

代码如下:

package main

import (
    "runtime"
)

var (
    LEN1 = 200000
    LEN2 = 1024
)

func f() {
    for {
    }
}

func main() {
    runtime.GOMAXPROCS(2)
    v := make(map[int][]int64, LEN1)

    for i := 0; i < LEN1; i++ {
        _v := make([]int64, LEN2)
        for j := 0; j < LEN2; j++ {
            _v[j] = int64(j)
        }
        v[i] = _v
    }

    go f()

    for {
        for i := 0; i < LEN1; i++ {
            for j := 0; j < LEN2; j++ {
                v[i][j] += 1
                v[i][j] -= 1
            }
        }
    }

}

操作系统启动后,不启动其它服务,CPU利用率约 1%~2%

测试结果:
程序启动后,2核CPU 全部跑满,GO程序达到 200%,过了两三分钟后,只有一个 CPU 到达 100%,另一个CPU却是 0%,Go程序 CPU利用率 是 100%

Go程序有两个 goruntine,可完全利用 2核CPU,但不知为何另一个 CPU 的利用率突然间变成了 0%

当然,这也有可能是 GO 做了优化(因为其中一个 goruntine 是空循环)!当在 f() 函数中也添加一下逻辑代码,如v := 1; v+=1; v-=1;,CPU利用率始终是 200%

回复了 zhouk_vcy 创建的主题: 请问各位,channel是协程安全的吗? 2016-10-28 18:19

发送一个数据到Channel从Channel接收一个数据 都是 原子性的

Go的哲学之一就是:不要通过共享内存来通信,而要通过通信来共享内存,前者就是传统的加锁,后者就是Channel。也就是说,设计Channel的主要目的就是在多任务间传递数据的,这当然是安全的。

回复了 samuier 创建的主题: go中有没有类似python的装饰器 2016-10-21 10:30
回复了 yqmking 创建的主题: go语言编程 第四章 实例,channel不理解 2016-05-03 13:04

IpcClient 中的 conn 是来源于 IpcServer 中的,见

func NewIpcClient(server *IpcServer) *IpcClient {
    c := server.Connect()
    return &IpcClient{c}
}

当调用 server.Connect() 时,会创建一个 channel,该 channel 就是 Connect 的返回值,在Connect方法中,专门启动了一个 Go 例程,接收这个 channel,然后去处理,并把处理结果发送回来,也就是说,client.conn <- string(b)是把参数传递过去进行处理,str := <- client.conn是取回处理后的结果。见 Connect 方法的实现:

func (server *IpcServer)Connect() chan string {
    session := make(chan string,0)

    go func (c chan string) {
        for  {
            request := <- c
            if request == "CLOSE" {
                break
            }
            var req Request
            err := json.Unmarshal([]byte(request),&req)
            if err != nil {
                fmt.Println("Invalid request format:",request)
            }
            resp := server.Handle(req.Method, req.Params)
            b, err := json.Marshal(resp)
            c <- string(b) //return result
        }
        fmt.Println("Session closed.")
    }(session)

    fmt.Println("A new session has been created successfully.")

    return session
}

见上面第15行。