一、数据类型转换

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:

go语言功能代码的更多相关文章

  1. 新手学python(2):C语言调用完成数据库操作

    继续介绍本人的python学习过程.本节介绍如何利用python调用c代码.内容还是基于音乐信息提取的过程,架构如图一.Python调用c实现的功能是利用python访问c语言完成mysql数据库操作 ...

  2. python下wxpython程序国际化的实践(中文英文切换)

    一.什么是python的国际化(I18N) 有关I18N,百度上解释一大堆,个人比较喜欢这个说法. i18n是 Internationalization 这个英文的简写,因为International ...

  3. golang读写文件

    1. 标准输入输出 os提供了标准输入输出文件: Stdin = NewFile(uintptr(syscall.Stdin), "/dev/stdin") Stdout = Ne ...

  4. Django1.9开发博客(11)- 富文本与代码高亮

    TinyMCE是一个轻量级的基于浏览器的所见即所得编辑器,支持目前流行的各种浏览器,由JavaScript写成. 功能配置灵活简单(两行代码就可以将编辑器嵌入网页中),支持AJAX.另一特点是加载速度 ...

  5. C语言初学者代码中的常见错误与瑕疵(3)

    问题: n-1位数字 已知w是一个大于10但不大于1000000的无符号整数,若w是n(n≥2)位的整数,则求出w的后n-1位的数. 输入: 第一行为M,表示测试数据组数. 接下来M行,每行包含一个测 ...

  6. LINQ之路 3:C# 3.0的语言功能(下)

    在LINQ介绍一篇中,我们已经看到了隐式类型变量var,扩展方法(Extension method)和Lambda表达式的身影.没错,他们正是LINQ技术的基石,是他们让LINQ的实现成为可能,并且简 ...

  7. LINQ之路 2:C# 3.0的语言功能(上)

    在上一篇的LINQ介绍中,我们已经看到了隐式类型变量var,扩展方法(extension method)和lambda表达式的身影.没错,他们正是LINQ技术的基石,是他们让LINQ的实现成为可能,并 ...

  8. 使用 Java 8 语言功能

    Android Studio 3.0 及以上版本支持所有 Java 7 语言功能,以及部分 Java 8 语言功能(具体因平台版本而异). 本页介绍您可以使用的 Java 8 语言功能.如何正确配置项 ...

  9. Cocos Creator代码编辑环境配置

    1,可以使用较为适合js的webstorm,亦可以采用VS: 2,若需要webstorm,在下载之后,在文件,设置内外部编辑器选用webstorm.exe,即可: 3,Visual Studio Co ...

随机推荐

  1. day 46 html 学习 列 表格,

    列表 1.无序列表 <ul type="disc"> <li>第一项</li> <li>第二项</li> </ul ...

  2. pnpm 快速节省磁盘工具的包管理工具

    nodejs 相关的包管理工具有很多,我们常用的有 npm cnpm(我基本已经不用了),yarn... pnpm 是另外一个不错的包管理工具,包含以下特性 快速 节省空间,一个版本的包只会在磁盘中存 ...

  3. 为什么 PCB 生产时推荐出 Gerber 给工厂?

    为什么 PCB 生产时推荐出 Gerber 给工厂? 事情是这样的,有一天电工王工,画了一块 PCB,发给 PCB 板厂. 过了几天 PCB 回来了,一看不对呀,这里的丝印怎么少了,那里怎么多了几条线 ...

  4. mysql全备和增量备份以及恢复过程(percona工具)

    实验环境 系统环境,内核版本和xtrabackup工具版本 [root@linux-node1 mysql]# cat /etc/redhat-release CentOS Linux release ...

  5. Percona XtraDB Cluster 的一些使用限制(PXC 5.7)

    Percona XtraDB Cluster有众多的优秀特性,使得mysql集群得以轻松实现.但是不要忽略了它的一些限制.如果你无法接受,或者你的应用程序或数据库(比如使用了memory引擎)对限制无 ...

  6. egg 官方文档之:框架扩展(Application、Context、Request、Response、Helper的访问方式及扩展)

    地址:https://eggjs.org/zh-cn/basics/extend.html Application app 对象指的是 Koa 的全局应用对象,全局只有一个,在应用启动时被创建. 访问 ...

  7. MySQL锁机制&&PHP锁机制,应用在哪些场景中呢?

    正文内容 模拟准备--如何模拟高并发访问一个脚本:apache安装文件的bin/ab.exe可以模拟并发量 -c 模拟多少并发量 -n 一共请求多少次 http://请求的脚本 C:\phpStudy ...

  8. RHEL 6.5系统安装配置图解教程(rhel-server-6.5)

    转自:http://www.jb51.NET/os/128752.html 说明: 截止目前RHEL 6.x最新版本为RHEL 6.5,下面介绍RHEL 6.5的具体安装配置过程 服务器相关设置如下: ...

  9. php限制文件下载速度的代码

    有时候你会出于某种目的而要求把下载文件的速度放慢一些,例如你想实现文件下载进度条功能.限制下载速度最大的好处是节省带宽,避免瞬时流量过大而造成网络堵塞.本文将和你分享如何通过php代码来实现限制文件的 ...

  10. jQuery模态框实现 后台添加删除修改Ip端口

    主要用到,$('#i1').each(),标签里绑定函数可传参数this <!DOCTYPE html> <html lang="en"> <head ...