package main import ( "fmt" "strconv" ) func main() { //int到string str := strconv.Itoa(int(1)) fmt.Println("int轉string", str) //int64到string str2 := strconv.FormatInt(int64(1), 10) fmt.Println("int64轉string", str2) //float64轉string formatFloat只能接收float64若是想用float32須要強轉float64(float32(0.8)) //下面是參數說明 // 'b' (-ddddp±ddd,二進制指數) // 'e' (-d.dddde±dd,十進制指數) // 'E' (-d.ddddE±dd,十進制指數) // 'f' (-ddd.dddd,沒有指數) // 'g' ('e':大指數,'f':其它狀況) // 'G' ('E':大指數,'f':其它狀況) str3 := strconv.FormatFloat(float64(0.8), 'f', -1, 32) fmt.Println("float32轉string", str3) //string到int 有異常的都不進行處理這個後面說 i, _ := strconv.Atoi("10") fmt.Println("strin轉int", i) //string 到int64 i64, _ := strconv.ParseInt("123", 10, 64) fmt.Println("strin轉int64", i64) //string轉float64 若是想轉float32 用float32(fl32)強轉一下就能夠 fl32, _ := strconv.ParseFloat("3.1415926535", 32/64) fmt.Println("strin轉float64", fl32) }
package main import ( "fmt" "time" ) func main() { //獲取當前時間 now := time.Now() //時間轉化爲string //在go語言裏將日期格式化並非yyyy-MM-dd HH:ss:mm 而是用"2006-01-02 15:04:05具體含義以下 //月份 1,01,Jan,January //日 2,02,_2 //時 3,03,15,PM,pm,AM,am //分 4,04 //秒 5,05 //年 06,2006 //周幾 Mon,Monday //時區時差表示 -07,-0700,Z0700,Z07:00,-07:00,MST //時區字母縮寫 MST timeStr := now.Format("2006-01-02 15:04:05") fmt.Println("日期類型當前時間: ", now) fmt.Println("字符串類型當前時間: ", timeStr) //string轉化爲時間 date, _ := time.Parse("2006-01-02 15:04:05", "2017-08-29 08:37:18") fmt.Println("string轉日期:", date) //判斷兩個時間前後 trueOrFalse := date.After(now) if trueOrFalse == true { fmt.Println("2017-08-29 08:37:18在", timeStr, "以後") } else { fmt.Println("2017-08-29 08:37:18在", timeStr, "以前") } // ParseDuration parses a duration string. // A duration string is a possibly signed sequence of decimal numbers, // each with optional fraction and a unit suffix, // such as "300ms", "-1.5h" or "2h45m". // Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". // -表明時間以前,不加表明時間以後 m表示分鐘,如20分鐘前 m, _ := time.ParseDuration("-20m") m1 := now.Add(m) fmt.Println("10分鐘以前:", m1) // h表明小時 一天以前爲-24h h, _ := time.ParseDuration("-8h") h1 := now.Add(h) fmt.Println("8小時以前", h1) // // 一天前 d, _ := time.ParseDuration("-24h") d1 := now.Add(d) fmt.Println(d1) //計算兩個時間差幾秒 sec := now.Sub(m1) fmt.Println(sec.Seconds(), "秒") //計算兩個時間差幾分鐘 minutes := now.Sub(m1) fmt.Println(minutes.Minutes(), "分鐘") //計算兩個時間差幾小時 hours := now.Sub(h1) fmt.Println(hours.Hours(), "小時") //計算兩個時間差幾天 day := now.Sub(d1) fmt.Println(day.Hours()/24, "天") //注意:splite3數據庫中字段若是是datetime類型獲取數據時格式轉換會有問題 //如2017-08-29 08:37:18這樣的時間從數據庫獲取後會變成2017-08-29T08:37:18Z //進行格式轉化以後不能比較,因此須要將T和Z替換爲" " //不知道其餘數據庫有沒有這樣的問題 }
package main import ( "flag" "sync" "github.com/larspensjo/config" ) var Conf_Main_Topic = "DEFAULT" var ( //config.ini爲配置文件格式爲 key=value configFile = flag.String("configfile", "config.ini", "General configuration file") ) var commonConf = make(map[string]string) var lock sync.RWMutex func LoadCommonConfiguration() { lock.Lock() defer lock.Unlock() cfg, err := config.ReadDefault(*configFile) if err != nil { //.... } commonConf = make(map[string]string) if cfg.HasSection(Conf_Main_Topic) { section, err := cfg.SectionOptions(Conf_Main_Topic) if err != nil { //.... } for _, v := range section { options, err := cfg.String(Conf_Main_Topic, v) if err != nil { //.... } commonConf[v] = options } } } //經過GetConf方法將key傳入獲取value值 func GetConf(key string) string { lock.RLock() defer lock.RUnlock() return commonConf[key] }
package main import ( "encoding/json" "strings" // "github.com/bitly/go-simplejson" // for json get ) //把兩層嵌套結構的json格式的數據組轉成map(map中不含interface結構) func NoInterfaceJsonToMap(input string) (map[string]map[string]interface{}, error) { result := make(map[string]map[string]interface{}) err := json.Unmarshal([]byte(input), &result) if err != nil { return nil, err } return result, nil } func MapToJson(input map[string]interface{}) (string, error) { result, err := json.Marshal(input) if err != nil { // panic(err) return "", err } return string(result), nil } func MapMapToJson(input map[string]map[string]interface{}) (string, error) { result, err := json.Marshal(input) if err != nil { return "", err } return string(result), nil } func JsonToMap(input string) (map[string]interface{}, error) { result := make(map[string]interface{}) err := json.Unmarshal([]byte(input), &result) if err != nil { return nil, err } return result, nil } func BoltKeyValueToJson(key, value string, delimeter string) (string, error) { keys := []string{key} values := []string{value} return BoltKeyValuesToJson(keys, values, delimeter) } func BoltKeyValuesToJson(keys, values []string, delimeter string) (string, error) { mapResult := make(map[string]interface{}) for i := range keys { key := strings.Split(keys[i], delimeter) value := values[i] cur := mapResult for j := range key { if j == len(key)-1 { } else if j == len(key)-2 { if cur[key[j]] == nil { cur[key[j]] = map[string]string{key[len(key)-1]: value} } else { cur[key[j]].(map[string]string)[key[len(key)-1]] = value } } else { if cur[key[j]] == nil { cur[key[j]] = make(map[string]interface{}) } cur = cur[key[j]].(map[string]interface{}) } } } return MapToJson(mapResult) }
package main import ( "bytes" "errors" "fmt" "io/ioutil" "net/http" "strconv" "strings" ) func HttpPostByJSON(accessUrl string, json string, redo int) error { fmt.Println(json) fmt.Println("post write json bytes:" + strconv.Itoa(len(json))) for j := 1; j <= redo; j++ { req_new := bytes.NewBuffer([]byte(json)) request, err := http.NewRequest("POST", accessUrl, req_new) if err == nil { request.Header.Set("Content-Type", "application/json;charset=UTF-8") client := http.Client{} response, err1 := client.Do(request) if err1 == nil { body, err := ioutil.ReadAll(response.Body) if err != nil { fmt.Println("Unknown error in sending Email") } else { resp := string(body) if strings.Contains(resp, "\"code\":\"200\"") { return nil } else { fmt.Println(string(body)) } } } else { fmt.Println(err1) } } else { fmt.Println(err) } } return errors.New("Fail to send email notification") }
package main import ( "bufio" "fmt" "io" "os" "strings" ) func FileExist(filename string) bool { _, err := os.Stat(filename) if os.IsNotExist(err) { return false } fmt.Println(err) return err == nil || os.IsExist(err) } func ReadFileByLine(filename string) []string { if !FileExist(filename) { return []string{} } f, err := os.Open(filename) fmt.Println(err) defer f.Close() rd := bufio.NewReader(f) result := []string{} for { line, err := rd.ReadString('\n') if err == nil || io.EOF == err { line = strings.TrimSpace(line) if len(line) > 0 { result = append(result, line) } } if io.EOF == err { break } fmt.Println(err) } return result } func WriteFileByLine(filename string, data []string) { f, err := os.Create(filename) fmt.Println(err) defer f.Close() wt := bufio.NewWriter(f) for i := range data { _, err := wt.WriteString(data[i]) if io.EOF == err { break } fmt.Println(err) } wt.Flush() } func DeleteFile(filename string) { if FileExist(filename) { err := os.Remove(filename) fmt.Println(err) } }
package main import ( "errors" "fmt" "os/exec" "runtime" "strings" ) func runInLinux(cmd string) string { fmt.Println("Running Linux Cmd:" + cmd) result, err := exec.Command("/bin/sh", "-c", cmd).Output() if err != nil { fmt.Println(err.Error()) } return strings.TrimSpace(string(result)) } func runInWindows(cmd string) string { fmt.Println("Running Win Cmd:" + cmd) result, err := exec.Command("cmd", "/c", cmd).Output() if err != nil { fmt.Println(err.Error()) } return strings.TrimSpace(string(result)) } func RunCommand(cmd string) string { if runtime.GOOS == "windows" { return runInWindows(cmd) } else { return runInLinux(cmd) } } func RunLinuxCommand(cmd string) string { if runtime.GOOS == "windows" { return "" } else { return runInLinux(cmd) } } func runInLinuxWithErr(cmd string) (string, error) { fmt.Println("Running Linux Cmd:" + cmd) result, err := exec.Command("/bin/sh", "-c", cmd).Output() if err != nil { fmt.Println(err.Error()) } return strings.TrimSpace(string(result)), err } func runInWindowsWithErr(cmd string) (string, error) { fmt.Println("Running Win Cmd:" + cmd) result, err := exec.Command("cmd", "/c", cmd).Output() if err != nil { fmt.Println(err.Error()) } return strings.TrimSpace(string(result)), err } func RunCommandWithErr(cmd string) (string, error) { if runtime.GOOS == "windows" { return runInWindowsWithErr(cmd) } else { return runInLinuxWithErr(cmd) } } func RunLinuxCommandWithErr(cmd string) (string, error) { if runtime.GOOS == "windows" { return "", errors.New("could not run in windows OS") } else { return runInLinuxWithErr(cmd) } }
Golang 有2個內置的函數 panic() 和 recover(),用以報告和捕獲運行時發生的程序錯誤,與 error 不一樣,panic-recover 通常用在函數內部。必定要注意不要濫用 panic-recover,可能會致使性能問題,我通常只在未知輸入和不可靠請求時使用。html
golang 的錯誤處理流程:當一個函數在執行過程當中出現了異常或遇到 panic(),正常語句就會當即終止,而後執行 defer 語句,再報告異常信息,最後退出 goroutine。若是在 defer 中使用了 recover() 函數,則會捕獲錯誤信息,使該錯誤信息終止報告。linux
package main import ( "log" "strconv" ) //捕獲因未知輸入致使的程序異常 func catch(nums ...int) int { defer func() { if r := recover(); r != nil { log.Println("[E]", r) } }() return nums[1] * nums[2] * nums[3] //index out of range } //主動拋出 panic,不推薦使用,可能會致使性能問題 func toFloat64(num string) (float64, error) { defer func() { if r := recover(); r != nil { log.Println("[W]", r) } }() if num == "" { panic("param is null") //主動拋出 panic } return strconv.ParseFloat(num, 10) } func main() { catch(2, 8) toFloat64("") }
go語言有異常的返回會有兩個返回參數包括值跟error,判斷error是否爲nil進行相應處理就能夠最好不要panicgit
package main import ( "database/sql" "errors" "fmt" "sync" _ "github.com/mattn/go-sqlite3" ) var db *sql.DB var dbLock sync.Mutex func main() { //查詢調用RunQuery或者RunQueryWithErr //?爲佔位符對應相應參數 rows := RunQuery("select age from table where id = ? and name = ?", 1, "abc") //也可使用struct構建對象,獲取數據庫字段時須要用sql.Null...不然取空值會報錯 var age sql.NullInt64 var ages []Int64 //若是有多條返回值用for循環遍歷,若是肯定只有一條能夠用if,這裏只有一條因此用if,也能夠將if改成for if rows.Next() { err := rows.Scan(&age) if err != nil { //........ } //sql.NullInt64中有兩個方法Int64和Valid,Valid用來判斷值是否爲空返回值爲true、false //Int64爲實際值,sql.NullInt64對象若是爲空Int64值爲0 if age.Valid { //對獲取到的age作操做 fmt.Println(age.Int64) } } //sqlite3中使用完rows以後必定要調用close釋放鎖,不然繼續調用數據庫語句會報數據庫被鎖的異常 rows.Close() //sqlite3中查詢和增刪改不能同時進行,也會報數據庫被鎖的異常 //須要在查詢以後統一進行增刪改操做,增刪改調用ExecSQL或ExecSqlWithErr } func OpenDB() { var err error //foo.db爲數據庫名字 db, err = sql.Open("sqlite3", "./foo.db?_txlock=exclusive") fmt.Println(err) _, err = db.Exec("PRAGMA synchronous = OFF;") fmt.Println(err) } func CloseDB() { if db != nil { err := db.Close() db = nil fmt.Println(err) } } func ExecSQL(query string, args ...interface{}) sql.Result { dbLock.Lock() defer dbLock.Unlock() if db == nil { OpenDB() } if query == "" { panic("Empty sql input") } fmt.Println("Running Exec:") fmt.Println(query) fmt.Println(args...) res, err := db.Exec(query, args...) fmt.Println(err) return res } func RunQuery(query string, args ...interface{}) *sql.Rows { dbLock.Lock() defer dbLock.Unlock() if db == nil { OpenDB() } if query == "" { panic("Empty sql input") } fmt.Println("Running Query:") fmt.Println(query) fmt.Println(args...) res, err := db.Query(query, args...) fmt.Println(err) return res } //多條語句的事物操做 func ExecTransaction(querys []string, args [][]string) { dbLock.Lock() defer dbLock.Unlock() if db == nil { OpenDB() } tx, err := db.Begin() fmt.Println(err) fmt.Println("Running Trans:") for index, query := range querys { if query == "" { panic("Empty sql input") } oldArgs := args[index] newArgs := make([]interface{}, len(oldArgs)) for i, v := range oldArgs { newArgs[i] = interface{}(v) } fmt.Println(query) fmt.Println(newArgs...) _, err := tx.Exec(query, newArgs...) fmt.Println(err) } err = tx.Commit() fmt.Println(err) } func OpenDBWithErr() error { var err error db, err = sql.Open("sqlite3", "./pjm.db?_txlock=exclusive") if err != nil { return err } _, err = db.Exec("PRAGMA synchronous = OFF;") return err } func CloseDBWithErr() error { if db != nil { err := db.Close() db = nil return err } return nil } func ExecSQLWithErr(query string, args ...interface{}) (sql.Result, error) { dbLock.Lock() defer dbLock.Unlock() if db == nil { err := OpenDBWithErr() if err != nil { return nil, err } } if query == "" { return nil, errors.New("Empty sql input") } fmt.Println("Running Exec With Err:") fmt.Println(query) fmt.Println(args...) return db.Exec(query, args...) } func RunQueryWithErr(query string, args ...interface{}) (*sql.Rows, error) { dbLock.Lock() defer dbLock.Unlock() if db == nil { err := OpenDBWithErr() if err != nil { return nil, err } } if query == "" { return nil, errors.New("Empty sql input") } fmt.Println("Running Query With Err:") fmt.Println(query) fmt.Println(args...) return db.Query(query, args...) } func ExecTransactionWithErr(querys []string, args [][]string) error { dbLock.Lock() defer dbLock.Unlock() if db == nil { err := OpenDBWithErr() if err != nil { return err } } tx, err := db.Begin() if err != nil { return err } fmt.Println("Running Trans With Err:") for index, query := range querys { if query == "" { return errors.New("Empty sql input") } oldArgs := args[index] newArgs := make([]interface{}, len(oldArgs)) for i, v := range oldArgs { newArgs[i] = interface{}(v) } fmt.Println(query) fmt.Println(newArgs...) _, err := tx.Exec(query, newArgs...) if err != nil { return err } } return tx.Commit() }
package main import ( "fmt" "html/template" "log" "net/http" "strings" ) func sayhelloName(w http.ResponseWriter, r *http.Request) { r.ParseForm() //解析url傳遞的參數,對於POST則解析響應包的主體(request body) //注意:若是沒有調用ParseForm方法,下面沒法獲取表單的數據 fmt.Println(r.Form) //這些信息是輸出到服務器端的打印信息 fmt.Println("path", r.URL.Path) fmt.Println("scheme", r.URL.Scheme) fmt.Println(r.Form["url_long"]) for k, v := range r.Form { fmt.Println("key:", k) fmt.Println("val:", strings.Join(v, "")) } fmt.Fprintf(w, "Hello astaxie!") //這個寫入到w的是輸出到客戶端的 } func login(w http.ResponseWriter, r *http.Request) { fmt.Println("method:", r.Method) //獲取請求的方法 //Handler裏面是不會自動解析form的,必須顯式的調用r.ParseForm()後,才能對這個表單數據進行操做 r.ParseForm() if r.Method == "GET" { t, _ := template.ParseFiles("login.html") t.Execute(w, nil) } else { //請求的是登錄數據,那麼執行登錄的邏輯判斷 fmt.Println("username:", r.Form["username"]) fmt.Println("password:", r.Form["password"]) //獲取username的值須要[0] if r.Form["username"][0] == "abc" { //若是username爲abc跳轉到user.html頁面打印abc===== t, _ := template.ParseFiles("./user.html") //t.Execute第二個參數能夠傳各類類型的數據到頁面 t.Execute(w, "abc=====") } else if r.Form["username"][0] == "efg" { t, _ := template.ParseFiles("./userMap.html") result := map[string]string{} result["key"] = "value" //返回map t.Execute(w, result) } else { t, _ := template.ParseFiles("./userMaps.html") result := []map[string]string{} m1 := map[string]string{} m2 := map[string]string{} m3 := map[string]string{} m1["a1"] = "111" m1["a2"] = "222" m1["a3"] = "333" m1["a4"] = "444" m2["a1"] = "555" m2["a2"] = "666" m2["a3"] = "777" m2["a4"] = "888" m3["a1"] = "999" m3["a2"] = "123" m3["a3"] = "456" m3["a4"] = "789" result = append(result, m1, m2, m3) //返回多個map t.Execute(w, result) } } } func main() { http.HandleFunc("/", sayhelloName) //設置訪問的路由 http.HandleFunc("/login", login) //設置訪問的路由 err := http.ListenAndServe(":9090", nil) //設置監聽的端口 if err != nil { log.Fatal("ListenAndServe: ", err) } }
login.html頁面github
<html> <head> <title></title> </head> <body> <form action="/login" method="post"> 用戶名:<input type="text" name="username"> 密碼:<input type="password" name="password"> <input type="submit" value="登錄"> </form> </body> </html>
<html> <head> <title></title> </head> <body> 從後臺獲取的值爲: {{.}} </body> </html>
userMap.html頁面golang
<html> <head> <title></title> </head> <body> 從後臺獲取的值爲: {{.key}} </body> </html>
userMaps.html頁面web
<html> <head> <title></title> </head> <body> {{range $index,$re :=.}} {{$re.a1}}</br> {{$re.a2}}</br> {{$re.a3}}</br> {{$re.a4}}</br> {{end}} </body> </html>
//分頁方法,根據傳遞過來的頁數,每頁數,總數,返回分頁的內容 7個頁數 前 1,2,3,4,5 後 的格式返回,小於5頁返回具體頁數 func Paginator(page, prepage int, nums int64) map[string]interface{} { var firstpage int //前一頁地址 var lastpage int //後一頁地址 //根據nums總數,和prepage每頁數量 生成分頁總數 totalpages := int(math.Ceil(float64(nums) / float64(prepage))) //page總數 if page > totalpages { page = totalpages } if page <= 0 { page = 1 } var pages []int switch { case page >= totalpages-5 && totalpages > 5: //最後5頁 start := totalpages - 5 + 1 firstpage = page - 1 lastpage = int(math.Min(float64(totalpages), float64(page+1))) pages = make([]int, 5) for i, _ := range pages { pages[i] = start + i } case page >= 3 && totalpages > 5: start := page - 3 + 1 pages = make([]int, 5) firstpage = page - 3 for i, _ := range pages { pages[i] = start + i } firstpage = page - 1 lastpage = page + 1 default: pages = make([]int, int(math.Min(5, float64(totalpages)))) for i, _ := range pages { pages[i] = i + 1 } firstpage = int(math.Max(float64(1), float64(page-1))) lastpage = page + 1 //fmt.Println(pages) } paginatorMap := make(map[string]interface{}) paginatorMap["pages"] = pages paginatorMap["totalpages"] = totalpages paginatorMap["firstpage"] = firstpage paginatorMap["lastpage"] = lastpage paginatorMap["currpage"] = page return paginatorMap }
html頁面sql
<div class="am-cf"> 共{{.totals}}條記錄 共記{{.paginator.totalpages}} 頁 當前頁 {{.paginator.currpage}} <div class="am-fr"> <ul class="am-pagination"> <li class=""><a href="/clubadmin/topics/{{.paginator.firstpage}}">«</a></li> {{range $index,$page := .paginator.pages}} <li {{if eq $.paginator.currpage $page }}class="am-active"{{end}}><a href="/clubadmin/topics/{{$page}}">{{$page}}</a></li> {{end}} <li><a href="/clubadmin/topics/{{.paginator.lastpage}}">»</a></li> </ul> </div> </div>
使用兩個 goroutine
交替打印序列,一個 goroutinue
打印數字, 另一個goroutine打印字母, 最終效果以下 12AB34CD56EF78GH910IJ 。數據庫
問題很簡單,使用 channel
來控制打印的進度。使用兩個 channel
,來分別控制數字和字母的打印序列, 數字打印完成後經過 channel
通知字母打印, 字母打印完成後通知數字打印,而後周而復始的工做。編程
runtime.GOMAXPROCS(runtime.NumCPU()) chan_n := make(chan bool) chan_c := make(chan bool, 1) done := make(chan struct{}) go func() { for i := 1; i < 11; i += 2 { <-chan_c fmt.Print(i) fmt.Print(i + 1) chan_n <- true } }() go func() { char_seq := []string{"A","B","C","D","E","F","G","H","I","J","K"} for i := 0; i < 10; i += 2 { <-chan_n fmt.Print(char_seq[i]) fmt.Print(char_seq[i+1]) chan_c <- true } done <- struct{}{} }() chan_c <- true <-done
代碼執行結果:json
12AB34CD56EF78GH910IJ
用戶隨機抽獎,數據結構以下所示:
// map中,key表明名稱,value表明成交單數 var users map[string]int64 = map[string]int64{ "a": 10, "b": 6, "c": 3, "d": 12, "f": 1, }
從map中選取隨機用戶,拿到這個編碼問題,有點懵逼,但仔細一想,只需把關注用戶的區間,轉變一下數據結構即解題。 把map轉成array,思考起來就簡單多了,原有問題變成了從0至n-1中選取一個數字,數字對應的用戶即中獎用戶。
package main import ( "fmt" "math/rand" "time" ) func GetAwardUserName(users map[string]int64) (name string) { sizeOfUsers := len(users) award_index := rand.Intn(sizeOfUsers) var index int for u_name, _ := range users { if index == award_index { name = u_name return } index += 1 } return } func main() { var users map[string]int64 = map[string]int64{ "a": 10, "b": 6, "c": 3, "d": 12, "e": 20, "f": 1, } rand.Seed(time.Now().Unix()) award_stat := make(map[string]int64) for i := 0; i < 1000; i += 1 { name := GetAwardUserName(users) if count, ok := award_stat[name]; ok { award_stat[name] = count + 1 } else { award_stat[name] = 1 } } for name, count := range award_stat { fmt.Printf("user: %s, award count: %d\n", name, count) } return }
代碼執行結果:
user: f, award count: 178 user: d, award count: 152 user: b, award count: 159 user: e, award count: 182 user: c, award count: 170 user: a, award count: 159
數據結構和上面一致,只是問題發生變化,須要更加用戶的成單數來抽獎,用戶成單越多,中獎機率越高,結構以下所示:
// map中,key表明名稱,value表明成交單數 var users map[string]int64 = map[string]int64{ "a": 10, "b": 6, "c": 3, "d": 12, "f": 1, }
這一題是上一題的延伸,加了訂單數進去,作爲權重來爲用戶抽獎。此題和上面的問題如此的類似,可把上面的問題, 理解成全部的用戶權重都相同的抽獎,而此題是權重不一樣的抽獎。解決此問題,依舊是把map轉爲數組來思考, 把各用戶的權重,從前到後依次拼接到數軸上,數軸的起點到終點即時中獎區間,而隨機數落到的那個用戶的區間,那個用戶即爲中獎用戶。
package main import ( "fmt" "math/rand" "time" ) func GetAwardUserName(users map[string]int64) (name string) { type A_user struct { Name string Offset int64 Num int64 } a_user_arr := make([]*A_user, 0) var sum_num int64 for name, num := range users { a_user := &A_user{ Name: name, Offset: sum_num, Num: num, } a_user_arr = append(a_user_arr, a_user) sum_num += num } award_num := rand.Int63n(sum_num) for index, _ := range a_user_arr { a_user := a_user_arr[index] if a_user.Offset+a_user.Num > award_num { name = a_user.Name return } } return } func main() { var users map[string]int64 = map[string]int64{ "a": 10, "b": 5, "c": 15, "d": 20, "e": 10, "f": 30, } rand.Seed(time.Now().Unix()) award_stat := make(map[string]int64) for i := 0; i < 10000; i += 1 { name := GetAwardUserName(users) if count, ok := award_stat[name]; ok { award_stat[name] = count + 1 } else { award_stat[name] = 1 } } for name, count := range award_stat { fmt.Printf("user: %s, award count: %d\n", name, count) } return }
代碼執行結果:
user: c, award count: 1667 user: f, award count: 3310 user: e, award count: 1099 user: d, award count: 2276 user: b, award count: 549 user: a, award count: 1099