/ 城寒 / Golang - Basic Usage

Golang - Basic Usage

2018-01-27 posted in [Golang]

命令行参数

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特有的一些格式要求,比如:

  1. 不能有没用的变量,没用到的import
  2. 对外提供的函数,首字母必须大写,否则不能被其他package使用。同一个package不同文件的函数和全局变量直接使用
  3. 尽量少使用异常,通过返回err进行判断和处理,panic在严重时才使用