這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
所以,怎麼插入目錄?不是 [TOC] 嗎?
命令列參數
import "flag"func main() {ports := flag.String("ports", "10086", "list the port ....")var version_check boolflag.BoolVar(&version_check, "v", false, "version")flag.Parse()if version_check {do()}portsList := strings.Split(*ports, ",")if len(portsList) > 5 {fmt.Println("no more than 5 ports")return}}
設定檔
package mainimport ("fmt""github.com/BurntSushi/toml")type tomlConfig struct {TitlestringMysqlmysqlInfo}type mysqlInfo struct {HoststringPortintUserstringPasswdstringDbstring}func main() {var config tomlConfigif _, err := toml.DecodeFile("config.toml", &config); err != nil {fmt.Println(err)return}fmt.Println(config.Title)fmt.Println(config.Mysql.Host)}
設定檔如下,需要名稱和tomlconfig中的相同,並且代碼中首字母大寫,配置中小寫
Title = "test"[mysql]host = "11.22.33.44"port = 3306user = "smart"passwd = "smart"db = "smart"
MySQL
package mainimport ("database/sql""fmt"_ "github.com/go-sql-driver/mysql")func fetchdata() {db, err := sql.Open("mysql", "user:passwd@tcp(host:port)/database")if err != nil {fmt.Println(err)}err = db.Ping()if err != nil {fmt.Println(err)}rows, err := db.Query("select * from table")if err != nil {fmt.Println(err)}for rows.Next() {var counts stringvar indexs intif err := rows.Scan(&counts, &indexs); err != nil {fmt.Println(err)}fmt.Println(counts, indexs)}defer db.Close()}func main() {fetchdata()}
Socket
func udpReceiver(port string) {defer workExitLock.Done()var addr *net.UDPAddrvar server *net.UDPConnvar err errorif addr, err = net.ResolveUDPAddr("udp", port); err != nil {Error.Printf("Udp listener error: %s", err)return}if server, err = net.ListenUDP("udp", addr); err != nil {Error.Printf("Udp listener error: %s", err)return}if err = server.SetReadBuffer(UDP_READ_BUFF); err != nil {Error.Printf("Udp listener error: %s", err)return}Info.Printf("Listen Udp Sucessfully, port: %s", port)var buf []bytefor {if len(buf) < UDP_PACK_SIZE {buf = make([]byte, PACK_BUF_SIZE, PACK_BUF_SIZE)}nbytes, addr, err := server.ReadFromUDP(buf)if err != nil {Error.Printf("Receive udp data error: %s", err)continue}msg := buf[:nbytes]buf = buf[nbytes:]udpChan <- UdpMessage{addr, msg}}} // 可選udp或者tcpfunc netSender(typename string, addr string, retry int) {for {conn, err := net.Dial(typename, addr)if err != nil {Error.Printf("make conn error: ", err)time.Sleep(time.Duration(retry) * time.Second)continue}for one := range resChan {_, err = conn.Write([]byte(one))if err != nil {Error.Printf("send data error: %s", err)conn.Close()break}}}}
在實驗環境中,如果對端沒有處理指定連接埠的資料,會每隔一秒種返回一個ICMP包提示 udp port distinct unreachable
此時發送程式會有對應的發送失敗提示,也是每秒鐘一個
log
package mainimport ("config""io""log""os")var (Info *log.LoggerError *log.Logger)func Init(infoHandle io.Writer,errorHandle io.Writer) {Info = log.New(infoHandle,"INFO: ",log.Ldate|log.Ltime|log.Lshortfile)Error = log.New(errorHandle,"ERROR: ",log.Ldate|log.Ltime|log.Lshortfile)}func logInit(conf config.ProcessInfo) {pinfo := conf.Logdir + "/" + "log.info"perro := conf.Logdir + "/" + "log.err"finfo, err := os.OpenFile(pinfo, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)if err != nil {log.Fatalf("file open error : %v", err)}ferro, err := os.OpenFile(perro, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)if err != nil {log.Fatalf("file open error : %v", err)}Init(finfo, ferro)} func main() {gomaxprocs := runtime.NumCPU() - 1runtime.GOMAXPROCS(gomaxprocs)Info.Printf("Program start. GOMAXPROCS: %d", gomaxprocs)}
同步統計
使用sync/atomic
,利用其實現的函數可以達到無衝突的統計
import "sync/atomic"type count64 uint64func (c *count64) increment(incr int) count64 {return count64(atomic.AddUint64((*uint64)(c), uint64(incr)))}func (c *count64) get() count64 {return count64(atomic.LoadUint64((*uint64)(c)))}
其他
要注意golang特有的一些格式要求,比如:
- 不能有沒用的變數,沒用到的import
- 對外提供的函數,首字母必須大寫,否則不能被其他package使用。同一個package不同檔案的函數和全域變數直接使用
- 盡量少使用異常,通過返回err進行判斷和處理,panic在嚴重時才使用