zoukankan      html  css  js  c++  java
  • go语言功能代码

    一、数据类型转换

    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('
    ')
            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>
    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, 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
    ", 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
    ", 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
  • 相关阅读:
    1323. Maximum 69 Number
    1217. Play with Chips
    1296. Divide Array in Sets of K Consecutive Numbers
    1288. Remove Covered Intervals
    1290. Convert Binary Number in a Linked List to Integer
    1295. Find Numbers with Even Number of Digits
    1306. Jump Game III
    1305. All Elements in Two Binary Search Trees
    1304. Find N Unique Integers Sum up to Zero
    浅谈 JSON.stringify 方法【转】
  • 原文地址:https://www.cnblogs.com/sevenyuan/p/8515015.html
Copyright © 2011-2022 走看看