Golang编程经验
??
Golang编程经验如何选择web框架:
Golang的web项目中的keepalive 关于keepalive,
server := &http.Server{ Addr: ":9999",Handler: framework,ReadTimeout: 32 * time.Second,WriteTimeout: 32 * time.Second,MaxHeaderBytes: 1 << 20,} server.ListenAndServe()
github.com/go-sql-driver/mysql使用主意事项: 这是使用率极高的一个库,
github.com/garyburd/redigo/redis使用注意事项: 这也是一个使用率极高的库, func initRedis(host string) *redis.Pool { return &redis.Pool{ MaxIdle: 64,IdleTimeout: 60 * time.Second,TestOnBorrow: func(c redis.Conn,t time.Time) error { _,err := c.Do("PING") return err },Dial: func() (redis.Conn,error) { c,err := redis.Dial("tcp",host) if err != nil { return nil,err } _,err = c.Do("SELECT",config.RedisDb) return c,err },} }
另外使用的时候也要把连接放回到池子里面,
如何全局捕获panic级别错误:
defer func() { if err := recover(); err != nil { lib.Log4e("Panic error",err) } }()
2.
最容易出错的地方: 使用指针,但是没有判断指针是否为nil,
如何获取程序执行栈:
defer func() { if err := recover(); err != nil { var st = func(all bool) string { // Reserve 1K buffer at first buf := make([]byte,512) for { size := runtime.Stack(buf,all) // The size of the buffer may be not enough to hold the stacktrace,// so double the buffer size if size == len(buf) { buf = make([]byte,len(buf)<<1) continue } break } return string(buf) } lib.Log4e("panic:" + toString(err) + "nstack:" + st(false)) } }()
具体方法就是调用
如何执行异步任务: 比如用户提交email, result := global.ResponseResult{ErrorCode: 0,ErrorMsg: "GetInviteCode success!"} render.JSON(200,&result) go func() { type data struct { Url string } name := "beta_test" subject := "We would like to invite you to the private beta of Screenshot." url := config.HttpProto + r.Host + "/user/register/" + *uniqid html := ParseMailTpl(&name,&beta_test_mail_content,data{url}) e := this.SendMail(mail,subject,html.String()) if e != nil { lib.Log4w("GetInviteCode,SendMail faild",mail,uniqid,e) } else { lib.Log4w("GetInviteCode,SendMail success",uniqid) } }()
思路是启动一个goroutine执行异步的操作,
如何使用定时器: 通常情况下, func Init() { ticker := time.NewTicker(30 * time.Minute) for { select { case c := <-global.TaskCmdChannel: switch *c { case "a": //todo } case c := <-global.TaskImageMessageChannel: m := new(model.TaskModel) m.Init() m.CreateImageMessage(c) m = nil case <-ticker.C: m := new(model.TaskModel) m.Init() m.CleanUserExpiredSessionKey() m = nil } } }
多goroutine执行如果避免发生竞态条件: Data 官方相关说明: http://blog.golang.org/race-detector http://golang.org/ref/mem
多goroutine执行,访问全局的变量,比如map,可能会发生竞态条件,
没有设置runtime.GOMAXPROCS会有竞态条件的问题吗? 答案是没有,
如何充分利用CPU多核: runtime.GOMAXPROCS(runtime.NumCPU()
解决并发情况下的竞态条件的方法: 1. 2. var mu sync.RWMutex … mu.RLock() defer mu.RUnlock() conns := h.all_connections[img_id] for _,c := range conns { if c == nil /*|| c.uid == uid */ { continue } select { case c.send <- []byte(message): default: h.conn_unregister(c) } }
使用锁有个主意的地方是避免死锁,比如循环加锁。
获取程序绝对路径: Golang编译出来之后是独立的可执行程序, func GetCurrPath() string { file,_ := exec.LookPath(os.Args[0]) path,_ := filepath.Abs(file) index := strings.LastIndex(path,string(os.PathSeparator)) ret := path[:index] return ret }
Golang函数默认参数: 大家都知道Golang是一门简洁的语言, func (this *ImageModel) GetImageListCount(project_id int64,paramter_optional ...int) int { var t int expire_time := 600 if len(paramter_optional) > 0 { expire_time = paramter_optional[0] } ... }
性能监控: go func() { profServeMux := http.NewServeMux() profServeMux.HandleFunc("/debug/pprof/",pprof.Index) profServeMux.HandleFunc("/debug/pprof/cmdline",pprof.Cmdline) profServeMux.HandleFunc("/debug/pprof/profile",pprof.Profile) profServeMux.HandleFunc("/debug/pprof/symbol",pprof.Symbol) err := http.ListenAndServe(":7789",profServeMux) if err != nil { panic(err) } }()
接下来就可以使用go
如何进行程序调试: 对于调试,每个人理解不一样,
守护进程(daemon) 下面给出完整的真正可用的例子: package main import ( "fmt" "log" "os" "runtime" "syscall" "time" ) func daemon(nochdir,noclose int) int { var ret,ret2 uintptr var err syscall.Errno darwin := runtime.GOOS == "darwin" // already a daemon if syscall.Getppid() == 1 { return 0 } // fork off the parent process ret,ret2,err = syscall.RawSyscall(syscall.SYS_FORK,0) if err != 0 { return -1 } // failure if ret2 < 0 { os.Exit(-1) } // handle exception for darwin if darwin && ret2 == 1 { ret = 0 } // if we got a good PID,then we call exit the parent process. if ret > 0 { os.Exit(0) } /* Change the file mode mask */ _ = syscall.Umask(0) // create a new SID for the child process s_ret,s_errno := syscall.Setsid() if s_errno != nil { log.Printf("Error: syscall.Setsid errno: %d",s_errno) } if s_ret < 0 { return -1 } if nochdir == 0 { os.Chdir("/") } if noclose == 0 { f,e := os.OpenFile("/dev/null",os.O_RDWR,0) if e == nil { fd := f.Fd() syscall.Dup2(int(fd),int(os.Stdin.Fd())) syscall.Dup2(int(fd),int(os.Stdout.Fd())) syscall.Dup2(int(fd),int(os.Stderr.Fd())) } } return 0 } func main() { daemon(0,1) for { fmt.Println("hello") time.Sleep(1 * time.Second) } }
进程管理: 个人比较喜欢用supervisord来进行进程管理,支持进程自动重启,supervisord是一个python开发的工具,
代码热更新: 代码热更新一直是解释型语言比较擅长的,Golang里面不是做不到,只是稍微麻烦一些,
条件编译: 条件编译时一个非常有用的特性,一般一个项目编译出一个可执行文件,但是有些情况需要编译成多个可执行文件,执行不同的逻辑,这比通过命令行参数执行不同的逻辑更清晰.比如这样一个场景,一个web项目,是常驻进程的, 1.在main.go头部加上// 2. 3. 4.
官方说明: Build
A
To
如果将项目有关资源文件打包进主程序: 使用go
与C/C++ 1. 2.Swig, 3.
其他: 近几年最热门的技术之一Docker是用Golang开发的, 已经有相关的书出版, 对系统运维,云计算感兴趣的可以了解。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |