一、数据类型转换

package main

import (
"fmt"
"strconv"
) func main() {
//int到string
str := strconv.Itoa(int())
fmt.Println("int转string", str)
//int64到string
str2 := strconv.FormatInt(int64(), )
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', -, )
fmt.Println("float32转string", str3)
//string到int 有异常的都不进行处理这个后面说
i, _ := strconv.Atoi("")
fmt.Println("strin转int", i)
//string 到int64
i64, _ := strconv.ParseInt("", , )
fmt.Println("strin转int64", i64)
//string转float64 如果想转float32 用float32(fl32)强转一下就可以
fl32, _ := strconv.ParseFloat("3.1415926535", /)
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()/, "天")
//注意: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)- {
} else if j == len(key)- {
if cur[key[j]] == nil {
cur[key[j]] = map[string]string{key[len(key)-]: value}
} else {
cur[key[j]].(map[string]string)[key[len(key)-]] = 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 := ; 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) > {
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[] * nums[] * nums[] //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, )
}
func main() {
catch(, )
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 = ?", , "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"][] == "abc" {
//如果username为abc跳转到user.html页面打印abc=====
t, _ := template.ParseFiles("./user.html")
//t.Execute第二个参数可以传各种类型的数据到页面
t.Execute(w, "abc=====")
} else if r.Form["username"][] == "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"] = ""
m1["a2"] = ""
m1["a3"] = ""
m1["a4"] = ""
m2["a1"] = ""
m2["a2"] = ""
m2["a3"] = ""
m2["a4"] = ""
m3["a1"] = ""
m3["a2"] = ""
m3["a3"] = ""
m3["a4"] = ""
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>
user.html页面
go语言中页面获取值必须加{{  }}
<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, )
done := make(chan struct{}) go func() {
for i := ; i < ; i += {
<-chan_c
fmt.Print(i)
fmt.Print(i + )
chan_n <- true
}
}() go func() {
char_seq := []string{"A","B","C","D","E","F","G","H","I","J","K"}
for i := ; i < ; i += {
<-chan_n
fmt.Print(char_seq[i])
fmt.Print(char_seq[i+])
chan_c <- true
}
done <- struct{}{}
}() chan_c <- true
<-done

代码执行结果:

12AB34CD56EF78GH910IJ

随机抽奖

问题描述

用户随机抽奖,数据结构如下所示:

// map中,key代表名称,value代表成交单数
var users map[string]int64 = map[string]int64{
"a": ,
"b": ,
"c": ,
"d": ,
"f": ,
}

解决思路

从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 +=
}
return
} func main() {
var users map[string]int64 = map[string]int64{
"a": ,
"b": ,
"c": ,
"d": ,
"e": ,
"f": ,
} rand.Seed(time.Now().Unix())
award_stat := make(map[string]int64)
for i := ; i < ; i += {
name := GetAwardUserName(users)
if count, ok := award_stat[name]; ok {
award_stat[name] = count +
} else {
award_stat[name] =
}
} for name, count := range award_stat {
fmt.Printf("user: %s, award count: %d\n", name, count)
} return
}

代码执行结果:

user: f, award count:
user: d, award count:
user: b, award count:
user: e, award count:
user: c, award count:
user: a, award count:

权重抽奖

问题描述

数据结构和上面一致,只是问题发生变化,需要更加用户的成单数来抽奖,用户成单越多,中奖概率越高,结构如下所示:

// map中,key代表名称,value代表成交单数
var users map[string]int64 = map[string]int64{
"a": ,
"b": ,
"c": ,
"d": ,
"f": ,
}

解决思路

这一题是上一题的延伸,加了订单数进去,做为权重来为用户抽奖。此题和上面的问题如此的相似,可把上面的问题, 理解成所有的用户权重都相同的抽奖,而此题是权重不同的抽奖。解决此问题,依旧是把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, )
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": ,
"b": ,
"c": ,
"d": ,
"e": ,
"f": ,
} rand.Seed(time.Now().Unix())
award_stat := make(map[string]int64)
for i := ; i < ; i += {
name := GetAwardUserName(users)
if count, ok := award_stat[name]; ok {
award_stat[name] = count +
} else {
award_stat[name] =
}
} for name, count := range award_stat {
fmt.Printf("user: %s, award count: %d\n", name, count)
} return
}

代码执行结果:

user: c, award count:
user: f, award count:
user: e, award count:
user: d, award count:
user: b, award count:
user: a, award count:

最新文章

  1. SQL优化技术分析-4:其他
  2. [Xilinx]Modelsim独立仿真Vivado生成的PLL核
  3. Linux-read命令
  4. mybatis中#和$符号的区别
  5. 用Maonry如何实现UIScrollView
  6. hdu - 2102 A计划 (简单bfs)
  7. PHP持续保有长连接,利用flush持续更新浏览器UI,下载进度条实现
  8. jquery data方法取值与js attr取值的区别
  9. MVC bootstrap-table显示数据时显示No matching records found
  10. Spring MVC 搭建
  11. js 取消事件冒泡
  12. Java开发 - 异常 - 抛出异常
  13. parseConf(配置文件解析器)
  14. Excel的方向键失灵
  15. jquery设置按钮disabled
  16. ASP.NET底层与各个组件的初步认识与理解 (转载)
  17. 2015 UESTC 搜索专题E题 吴队长征婚 爆搜
  18. 安装pip环境以及pip常用命令使用
  19. Oracle recovery manager failed to restore
  20. python基础===通过菲波那契数列,理解函数

热门文章

  1. pycharm远程调试配置
  2. C++中的继承和多继承
  3. How To Use the AWK language to Manipulate Text in Linux
  4. oracle参数文件与启动过程
  5. oracle-db安装
  6. c++内存泄漏原因及解决办法(智能指针)
  7. 子序列匹配(search,find_end,search_n)
  8. elastic 部分更新 retry_on_conflict 和 数据库写锁 详细比对
  9. Spring 集成Junit单元测试
  10. Flume 拦截器(interceptor)详解