一、数据类型转换
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] }
四、Json与Map转换
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) }
五、通过JSON数据发送Email
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) } }
七、go执行linux和windows命令操作
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,可能会导致性能问题,我一般只在未知输入和不可靠请求时使用。
golang 的错误处理流程:当一个函数在执行过程中出现了异常或遇到 panic(),正常语句就会立即终止,然后执行 defer 语句,再报告异常信息,最后退出 goroutine。如果在 defer 中使用了 recover() 函数,则会捕获错误信息,使该错误信息终止报告。
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进行相应处理就可以最好不要panic
十、数据库操作
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() }
十一、go语言web编程
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页面
<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页面
<html> <head> <title></title> </head> <body> 从后台获取的值为: {{.key}} </body> </html>
userMaps.html页面
<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页面
<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
代码执行结果:
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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· [AI/GPT/综述] AI Agent的设计模式综述