所以,怎么插入目录?不是 [TOC] 吗?
命令行参数
import "flag"
func main() {
ports := flag.String("ports", "10086", "list the port ....")
var version_check bool
flag.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 main
import (
"fmt"
"github.com/BurntSushi/toml"
)
type tomlConfig struct {
Title string
Mysql mysqlInfo
}
type mysqlInfo struct {
Host string
Port int
User string
Passwd string
Db string
}
func main() {
var config tomlConfig
if _, 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 = 3306
user = "smart"
passwd = "smart"
db = "smart"
MySQL
package main
import (
"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 string
var indexs int
if 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.UDPAddr
var server *net.UDPConn
var err error
if 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 []byte
for {
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或者tcp
func 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 main
import (
"config"
"io"
"log"
"os"
)
var (
Info *log.Logger
Error *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() - 1
runtime.GOMAXPROCS(gomaxprocs)
Info.Printf("Program start. GOMAXPROCS: %d", gomaxprocs)
}
同步统计
使用sync/atomic
,利用其实现的函数可以达到无冲突的统计
import "sync/atomic"
type count64 uint64
func (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在严重时才使用
有疑问加站长微信联系(非本文作者)