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开发的, 已经有相关的书出版, 对系统运维,云计算感兴趣的可以了解。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
