介绍

记录一些可能常用到的实例,便于快速查询

读文件

按字节读取文件

这种方式是以字节为单位来读取,相对底层一些,代码量也较大

  1. package main
  2. import (
  3. "fmt"
  4. "io"
  5. "os"
  6. )
  7. func main() {
  8. file,_ := os.Open("test.txt")
  9. defer file.Close()
  10. buf := make([]byte, 1024) // 每次读取1024字节
  11. var res string // 存放最终的结果
  12. for {
  13. count, err := file.Read(buf)
  14. if err == io.EOF { // 检测是否到结尾
  15. break
  16. } else {
  17. currBytes := buf[:count] // 读取了count字节
  18. res += string(currBytes) // 最终结果
  19. }
  20. }
  21. fmt.Println(res)
  22. }

借助ioutil来读取

由于 os.File 也是 io.Reader 的实现,我们可以调用 ioutil.ReadAll(io.Reader) 方法,将文件所有字节读取出来,省去了使用字节缓存循环读取的过程。

  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. )
  7. func main() {
  8. file,_ := os.Open("test.txt")
  9. defer file.Close()
  10. byteRes, _ := ioutil.ReadAll(file) // 返回存放结果的切片
  11. fmt.Printf("%T\n", byteRes) // []uint8
  12. fmt.Println(string(byteRes))
  13. }

仅使用ioutil包来完成读取操作

为了进一步简化文件读取操作,ioutil 还提供了 ioutil.ReadFile(filename string) 方法,一行代码搞定读取任务

  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. )
  6. func main() {
  7. data, _ := ioutil.ReadFile("test.txt")
  8. fmt.Println(string(data))
  9. }

利用Scanner按行读取

逐行读取文件内容,这个时候可以 Scanner 来完成

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "os"
  6. )
  7. func main() {
  8. file, _ := os.Open("test.txt")
  9. defer file.Close()
  10. scanner := bufio.NewScanner(file) // 类似Java中的Scanner
  11. for scanner.Scan() {
  12. fmt.Println(scanner.Text())
  13. }
  14. }

写文件

使用ioutil

刚才用到了ioutil.ReadFile,与之对应的,肯定也有WriteFile
该函数属于全覆盖写入,如果文件不存在,则会根据指定的权限创建文件,如果存在,则会先清空文件原有内容,然后再写入新数据

  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. )
  7. func main() {
  8. data := []byte("hello d4m1ts")
  9. fmt.Println(os.FileMode(0666).String()) // -rw-rw-rw-
  10. ioutil.WriteFile("test.txt", data, 0666)
  11. }

通过File句柄

os.OpenFile(name string, flag int, perm FileMode)方法,通过指定额外的 读写方式文件权限 参数,使文件操作变得更为灵活。
flag 有以下几种常用的值:

  • os.O_CREATE: create if none exists 不存在则创建
  • os.O_RDONLY: read-only 只读
  • os.O_WRONLY: write-only 只写
  • os.O_RDWR: read-write 可读可写
  • os.O_TRUNC: truncate when opened 文件长度截为0:即清空文件
  • os.O_APPEND: append 追加新数据到文件 ``` package main

import ( “fmt” “os” )

func main() { file,_ := os.OpenFile(“test.txt”, os.O_RDWR | os.O_APPEND | os.O_CREATE, 0666) // 按照特定权限打开 defer file.Close()

  1. data := []byte("hello d4m1ts")
  2. count, _ := file.Write(data) // 按字节写入,返回的count为写入的字节数
  3. fmt.Println(count)
  4. count, _ = file.WriteString("\nHello D4m1ts") // 按字符串写入
  5. fmt.Println(count)
  6. file.Sync() // 确保写入到磁盘

}

  1. ### 通过bufio包
  2. 这种方式其实是在File句柄上做了一层封装,调用方式和上面直接写入非常相似

package main

import ( “bufio” “fmt” “os” )

func main() { file,_ := os.OpenFile(“test.txt”, os.O_RDWR | os.O_APPEND | os.O_CREATE, 0666) defer file.Close()

  1. writer := bufio.NewWriter(file)
  2. data := []byte("hello d4m1ts")
  3. count, _ := writer.Write(data) // 按字节写入,返回的count为写入的字节数
  4. fmt.Println(count)
  5. count, _ = writer.WriteString("\nHello D4m1ts") // 按字符串写入
  6. fmt.Println(count)
  7. writer.Flush() // 清空缓存,确保写入到磁盘

}

  1. ## 正则表达式
  2. ### 匹配内容是否存在

package main

import ( “fmt” “regexp” )

func main() { regex := “\d{1,3}” res, := regexp.MatchString(regex, “123123”) res1, := regexp.MatchString(regex, “aaaa”) fmt.Println(res) // true fmt.Println(res1) // false

}

  1. ### 提取内容

package main

import ( “fmt” “regexp” )

func main() { regex, _ := regexp.Compile(“(\d{1,3})\d{1,3}”) // 编译正则表达式 fmt.Println(regex.MatchString(“123123123123”)) // true fmt.Println(regex.FindString(“123213123123”)) // 123213 返回第一个匹配的 fmt.Println(regex.FindStringIndex(“123213123123”)) // [0 6] 返回第一个匹配的开始和结尾的索引 fmt.Println(regex.FindStringSubmatch(“123213123123”)) // [123213 123] 返回包括()这种子匹配的 fmt.Println(regex.FindAllString(“123213123123”,-1)) // [123213 123123] 返回匹配的所有内容,n表示为返回个数,-1则返回全部 fmt.Println(regex.FindAllStringSubmatch(“123213123123”,-1)) // [[123213 123] [123123 123]] 同时返回子匹配的结果 fmt.Println(regex.FindAll([]byte(“123123123123”), -1)) // [[49 50 51 49 50 51] [49 50 51 49 50 51]] 通过字节去匹配,返回的也是字节的结果 }

  1. ### 替换内容

package main

import ( “fmt” “regexp” )

func main() { regex, _ := regexp.Compile(“(\d{1,3})\d{1,3}”) // 编译正则表达式 fmt.Println(regex.ReplaceAllString(“123123123213”,”a”)) // aa }

  1. ### 其他
  2. 在线正则表达式测试网站:[https://regex101.com/](https://regex101.com/)<br />golang正则匹配的时候,`.`默认是不匹配换行的,所以要匹配多行数据就容易出问题<br />这个时候可以采用如下格式,让`.`也可以匹配换行

(?s).*

  1. **实例:**<br />![image-20211229171038928](https://cdn.nlark.com/yuque/0/2022/png/2976988/1646986808303-721a2b18-3c7e-4f06-ba86-d54fa6acf210.png)
  2. ## JSON序列化和反序列化
  3. ### 标准JSON模块
  4. Go 语言标准库 `encoding/json` 提供了操作 JSON 的方法,一般可以使用 `json.Marshal` `json.Unmarshal` 来序列化和解析 JSON 字符串<br />**实例一:**

package main

import ( “encoding/json” “fmt” )

func main() { // 序列化 s1 := []string{“apple”, “peach”, “pear”} s2, _ := json.Marshal(s1) // 转字符串 fmt.Println(string(s2)) // [“apple”,”peach”,”pear”]

  1. // 反序列化
  2. var s3 [] string
  3. json.Unmarshal([]byte(s2), &s3) // 字符串恢复
  4. fmt.Println(s3) // [apple peach pear]
  5. fmt.Println(len(s3), s3[0]) // 3 apple

}

  1. **实例二:**

package main

import ( “encoding/json” “fmt” )

// 定义结构体,变量名注意大写,因为跨到json包了 type User struct { Name string Age int }

func main() { // 初始化结构体 user := User{ Name: “d4m1ts”, Age: 18, }

  1. // 序列化,转字符串
  2. s1, _ := json.Marshal(user)
  3. fmt.Println(string(s1))
  4. // 反序列化,恢复为原来的结构
  5. user2 := User{}
  6. json.Unmarshal(s1, &user2)
  7. fmt.Println(user2)

}

  1. ### 更优的jsoniter
  2. 标准库 `encoding/json` 在使用时需要预先定义结构体,使用时显得不够灵活。这时候可以尝试使用 `github.com/json-iterator/go` 模块,其除了**提供与标准库一样的接口之外,还提供了一系列更加灵活的操作方法**。

go get -v github.com/json-iterator/go

  1. ```
  2. package main
  3. import (
  4. "fmt"
  5. jsoniter "github.com/json-iterator/go"
  6. )
  7. func main() {
  8. // 反序列化,恢复为原来的结构
  9. s := `{"a":"b", "c":["d","e","f"]}`
  10. res := jsoniter.Get([]byte(s), "c")
  11. fmt.Println(res.ToString()) // ["d","e","f"] 只解析"c"的内容部分
  12. }

扩展

大多数时候获取的json数据可能是映射+切片形式的,只有上面的一些内容很难搞,所以还是补充一下
使用.GetInterface()会自动给结果转换为interface{},再通过这个结果继续转换,如[]interface{}
想要拿到最后的数据,只需要通过数据.(对应的格式)即可,如 aaa.(string)表示转换为string

[!note]

一步一步看吧,用.GetInterface()或者等报错提示,就可以看到应该转换的格式了,如下图右边就是可以转换的格式

image-20220131142914379

  1. func main() {
  2. strings := "{\"a\":[{\"b\":\"c\"}]}"
  3. var res interface{}
  4. res = jsoniter.Get([]byte(strings), "a").GetInterface()
  5. fmt.Println(res.([]interface{}))
  6. for _,i := range res.([]interface{}) {
  7. fmt.Println(i.(map[string]interface{}))
  8. }
  9. }

时间日期

  1. package main
  2. import (
  3. "fmt"
  4. "time"
  5. )
  6. func main() {
  7. p := fmt.Println
  8. // 现在的时间
  9. now := time.Now()
  10. p(now)
  11. // 休眠1秒
  12. time.Sleep(time.Second * 1)
  13. p(time.Now()) // 现在的时间
  14. // 格式类型转换
  15. t1, _ := time.Parse(time.RFC3339, "2012-11-01T22:08:41+00:00")
  16. p(t1) // 2012-11-01 22:08:41 +0000 +0000
  17. // 格式化输出
  18. p(now.Format("3:04PM")) // 5:14PM
  19. p(now.Format("Mon Jan _2 15:04:05 2006")) // Tue Dec 28 17:15:49 2021
  20. p(now.Format("2006-01-02T15:04:05.999999-07:00")) // 2021-12-28T17:15:49.121777+08:00
  21. p(now.Format(time.RFC850)) // Tuesday, 28-Dec-21 17:20:02 CST
  22. fmt.Printf("%d-%02d-%02dT%02d:%02d:%02d-00:00\n",
  23. now.Year(), now.Month(), now.Day(),
  24. now.Hour(), now.Minute(), now.Second()) // 2021-12-28T17:20:02-00:00
  25. }

随机数

伪随机数

Go的math/rand包提供伪随机数生成。例如,rand.Intn返回一个随机int n,0 <= n <100
伪随机生成的数字是确定的,不论在什么机器、什么时间,只要执行的随机代码一样,那么生成的随机数就一样

  1. package main
  2. import (
  3. "fmt"
  4. "math/rand"
  5. )
  6. func main() {
  7. p := fmt.Println
  8. p(rand.Int()) // 5577006791947779410
  9. p(rand.Int31n(int32(60))) // 27
  10. for i:=0; i<5; i+=1 {
  11. p(rand.Float64()) // 0.6645600532184904 每次执行的结果都是一样
  12. }
  13. }

真随机数

crypto/rand是为了提供更好的随机性满足密码对随机数的要求,在linux上已经有一个实现就是/dev/urandomcrypto/rand就是从这个地方读“真随机”数字返回,但性能比较慢

  1. package main
  2. import (
  3. "crypto/rand"
  4. "math/big"
  5. )
  6. func main() {
  7. for i := 0; i < 4; i++ {
  8. n, _ := rand.Int(rand.Reader, big.NewInt(100))
  9. println(n.Int64())
  10. }
  11. }

URL解析

可以直接使用url.Parse(string u)来解析,其中包括方案,身份验证信息,主机,端口,路径,查询参数和查询片段等信息

  1. package main
  2. import (
  3. "fmt"
  4. "net/url"
  5. )
  6. func main() {
  7. u := "https://admin:password@blog.gm7.org/test/point?a=123&b=test"
  8. uu, _ := url.Parse(u)
  9. fmt.Println(uu.Scheme)
  10. fmt.Println(uu.User)
  11. fmt.Println(uu.User.Username())
  12. fmt.Println(uu.Host)
  13. fmt.Println(uu.Path)
  14. fmt.Println(uu.Hostname())
  15. fmt.Println(uu.Query())
  16. }
  17. /*
  18. https
  19. admin:password
  20. admin
  21. blog.gm7.org
  22. /test/point
  23. blog.gm7.org
  24. map[a:[123] b:[test]]
  25. */

Base64

  1. package main
  2. import (
  3. "encoding/base64"
  4. "fmt"
  5. )
  6. func main() {
  7. a := "123456"
  8. res := base64.StdEncoding.EncodeToString([] byte(a))
  9. fmt.Println(res) // MTIzNDU2
  10. decod, _ := base64.StdEncoding.DecodeString(res)
  11. fmt.Println(string(decod)) // 123456
  12. }

命令行参数

从命令行获取参数,得到的是一个切片

  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. )
  6. func main() {
  7. args := os.Args
  8. fmt.Println(args)
  9. }
  10. /*
  11. go run Hello.go 123 456
  12. [/var/folders/fw/tddtsjp91wb9q64l5xt7jd540000gn/T/go-build3185553057/b001/exe/Hello 123 456]
  13. */

执行系统命令

在 Golang 中用于执行命令的库是 os/execexec.Command 函数返回一个 Cmd 对象,根据不同的需求,可以将命令的执行分为三种情况

  1. 只执行命令,不获取结果
  2. 执行命令,并获取结果(不区分 stdoutstderr
  3. 执行命令,并获取结果(区分 stdoutstderr

    只执行命令,不获取结果

    直接调用Run()函数 ``` package main

import ( “fmt” “os/exec” )

func main() { res := exec.Command(“open”, “-na”, “Calculator”).Run() // run会阻塞等到命令执行结束 fmt.Println(res) // }

  1. ### 执行命令获取结果
  2. 可以调用 `cmd` `CombinedOutput` 函数

package main

import ( “fmt” “os/exec” )

func main() { cmd := exec.Command(“ls”, “-la”) res, _ := cmd.CombinedOutput() fmt.Println(string(res)) // ls -la 执行结果 }

  1. ### 执行命令获取结果并区分`stdout`和`stderr`

package main

import ( “bytes” “fmt” “os/exec” )

func main() { cmd := exec.Command(“ls”, “-la”) var stdout, stderr bytes.Buffer cmd.Stdout = &stdout cmd.Stderr = &stderr cmd.Run()

  1. fmt.Println(string(stdout.Bytes())) // ls -la 执行结果

}

  1. ### 多条命令使用管道执行
  2. 就是类似`shell`里面`|`的作用,`ls -la | grep go`

package main

import ( “fmt” “os” “os/exec” )

func main() { cmd1 := exec.Command(“ls”, “-la”) cmd2 := exec.Command(“grep”, “go”) cmd2.Stdin, _ = cmd1.StdoutPipe() cmd2.Stdout = os.Stdout cmd2.Start() cmd1.Run() cmd2.Wait()

  1. fmt.Println(cmd2.Stdout) // ls -la | grep go 执行结果

}

  1. ### 扩展
  2. 前面每个空格间都需要单独一个参数,有时候很长就不方便,可以采用如下的方式来

cmd := exec.Command(“/bin/sh”,”-c”,”expr 2 + 33”)

  1. ## HTTP请求
  2. ### 快速发起get请求

package main

import ( “fmt” “io/ioutil” “net/http” )

func main() { url := “https://www.baidu.com/“ response, := http.Get(url) // 发起get请求 defer response.Body.Close() fmt.Println(response.StatusCode) fmt.Println(response.Header.Get(“Server”)) body, := ioutil.ReadAll(response.Body) fmt.Println(string(body)) // 源码 }

  1. 收到的数据包

GET / HTTP/1.1 Host: 127.0.0.1:8000 User-Agent: Go-http-client/1.1 Accept-Encoding: gzip

  1. ### 带有参数的GET请求
  2. 可以直接在上面的`url`后面直接构造参数,也可以通过如下的方式手动设置参数

package main

import ( “fmt” “net/http” “net/url” )

func main() { u := “http://baidu.com/“ Url, _ := url.Parse(u)

  1. param := url.Values{}
  2. param.Set("name", "d4m1ts")
  3. param.Set("中文", "汉字测试")
  4. Url.RawQuery = param.Encode() // 包含URL编码
  5. fmt.Println(Url) // http://baidu.com/?name=d4m1ts&%E4%B8%AD%E6%96%87=%E6%B1%89%E5%AD%97%E6%B5%8B%E8%AF%95
  6. resp,_ := http.Get(Url.String())
  7. fmt.Println(resp.StatusCode) // 200

}

  1. 收到的数据包

GET /?name=d4m1ts&%E4%B8%AD%E6%96%87=%E6%B1%89%E5%AD%97%E6%B5%8B%E8%AF%95 HTTP/1.1 Host: 127.0.0.1:8000 User-Agent: Go-http-client/1.1 Accept-Encoding: gzip

  1. ### 返回JSON的数据包
  2. 返回是json格式,如何快速格式化数据
  3. - 返回的json内容

{ “args”: {}, “headers”: { “Accept”: “text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9”, “Accept-Encoding”: “gzip, deflate”, “Accept-Language”: “zh-CN,zh;q=0.9,en;q=0.8”, “Dnt”: “1”, “Host”: “httpbin.org”, “Sec-Gpc”: “1”, “Upgrade-Insecure-Requests”: “1”, “User-Agent”: “Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36”, “X-Amzn-Trace-Id”: “Root=1-61cbb6de-6e8a5d6a2710be6f22da6f92” }, “origin”: “213.239.21.35”, “url”: “http://httpbin.org/get“ }

  1. - 一样的发起http请求,只是最后用JSON来反序列化而已

package main

import ( “fmt” jsoniter “github.com/json-iterator/go” “io/ioutil” “net/http” )

func main() { u := “http://httpbin.org/get“ resp, err := http.Get(u) if err == nil { // 请求成功 body, _ := ioutil.ReadAll(resp.Body)

  1. origin := jsoniter.Get(body, "origin")
  2. fmt.Println(origin.ToString()) // 213.239.21.35
  3. headers := jsoniter.Get(body, "headers")
  4. fmt.Println(headers.Get("Host").ToString()) // httpbin.org
  5. }

}

  1. ### 自定义Header头

package main

import ( “fmt” jsoniter “github.com/json-iterator/go” “io/ioutil” “net/http” “time” )

func main() { // 创建一个HTTP请求,但是不发送请求 u := “http://httpbin.org/get“ req, _ := http.NewRequest(“GET”, u, nil) req.Header.Set(“User-Agent”, “Test GO”) req.Header.Set(“Name”, “d4m1ts”)

  1. // 发送刚才创建的请求
  2. client := http.Client{
  3. Timeout: 3*time.Second, // 超时时间
  4. }
  5. resp, _ := client.Do(req)
  6. body, _ := ioutil.ReadAll(resp.Body)
  7. headers := jsoniter.Get(body, "headers")
  8. fmt.Println(headers.ToString())

}

/ { “Accept-Encoding”: “gzip”, “Host”: “httpbin.org”, “Name”: “d4m1ts”, “User-Agent”: “Test GO”, “X-Amzn-Trace-Id”: “Root=1-61cbbb0d-68f21a6c5c36abd861b6fe99” } /

  1. 收到的数据包

GET / HTTP/1.1 Host: 127.0.0.1:8000 User-Agent: Test GO Name: d4m1ts Accept-Encoding: gzip

  1. ### 快速发起POST请求
  2. **方法一:**使用`http.Post`,有一点点麻烦

package main

import ( “net/http” “strings” )

func main() { u := “http://127.0.0.1:8000“ http.Post(u, “application/x-www-form-urlencoded”, strings.NewReader(“aa=bb”)) }

  1. 收到的http请求

POST / HTTP/1.1 Host: 127.0.0.1:8000 User-Agent: Go-http-client/1.1 Content-Length: 5 Content-Type: application/x-www-form-urlencoded Accept-Encoding: gzip

aa=bb

  1. **方法二:**使用`http.PostForm`,相对简单,但是无法设置`content-type`,没那么自由

package main

import ( “net/http” “net/url” )

func main() { u := “http://127.0.0.1:8000“ param := url.Values{} param.Set(“aaa”, “bbb”) http.PostForm(u, param) }

  1. 收到的http请求

POST / HTTP/1.1 Host: 127.0.0.1:8000 User-Agent: Go-http-client/1.1 Content-Length: 7 Content-Type: application/x-www-form-urlencoded Accept-Encoding: gzip

aaa=bbb

  1. ### 自定义POST请求
  2. `get`差不多,只不过是多了设置`content-type`post数据的步骤而已<br />举例为发送json数据

package main

import ( “bytes” “encoding/json” “net/http” )

func main() { // 创建请求,但是不发起 u := “http://127.0.0.1:8000“ param := map[string]string{ “aa”: “bb”, “name”: “d4m1ts”, } buf, := json.Marshal(param) // 序列化的json req, := http.NewRequest(“POST”, u, bytes.NewReader(buf)) req.Header.Set(“User-Agent”, “UA TEST”) req.Header.Set(“Content-Type”, “application/json”)

  1. // 发送刚才的请求
  2. client := http.Client{}
  3. client.Do(req)

}

  1. 收到的http数据包

POST / HTTP/1.1 Host: 127.0.0.1:8000 User-Agent: UA TEST Content-Length: 27 Content-Type: application/json Accept-Encoding: gzip

{“aa”:”bb”,”name”:”d4m1ts”}

  1. ### 忽略证书
  2. 有些时候一些ssl网站因为证书问题也会抛出`panic`异常,所以一般可以忽略SSL证书,在初始化http客户端的时候忽略,代码如下

tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // 忽略SSL证书 } Client := http.Client{ Transport: tr, }

  1. ### cookieJar和代理设置

// 初始化Client jar, := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List}) proxy, := url.Parse(“socks5://127.0.0.1:1080”) netTransport := &http.Transport{ Proxy: http.ProxyURL(proxy), MaxIdleConnsPerHost: 10, ResponseHeaderTimeout: time.Second time.Duration(5), } Client = http.Client{ Transport: netTransport, Jar: jar, Timeout: time.Second 10, }

  1. Client.Get("http://cip.cc")
  1. ### gzip解压
  2. 有些返回的数据是二进制乱码的,这个时候我们就需要进行gzip解压
  1. resp, _ := Client.Do(req)
  2. reader,_ := gzip.NewReader(resp.Body)
  3. source, _ := ioutil.ReadAll(reader)
  4. fmt.Println(string(source))
  1. ## go flag
  2. 这个库主要用来判断工具命令行传入的参数用的<br />虽然go`os.Args`,但是不如这个好用<br />**演示:**

func main() { var filePath string flag.StringVar(&filePath, “file”, “”, “markdown文件路径”) flag.Parse() if flag.Lookup(“file”).DefValue == flag.Lookup(“file”).Value.String() { // 避免使用默认参数,所以加个判断 flag.Usage() } if flag.NFlag() == 0 { // 使用的命令行参数个数,这个地方可以用来判断用户是否输入参数(程序正常情况下会使用默认参数) flag.Usage() os.Exit(0) } }

  1. ![image-20220130171243948](https://cdn.nlark.com/yuque/0/2022/png/2976988/1646986810717-169ff82c-1fac-4f4e-8397-36f4f5161318.png)
  2. > [!NOTE]
  3. > 还有一些其他的参数,可以自己研究下,基本上看到名字就知道啥意思,主要用的就上面那些
  4. > 如果觉得帮助不好看,可以重写`flag.Usage()`这个方法
  5. >
  1. flag.Usage = func() {
  2. fmt.Fprintf(flag.CommandLine.Output(), "markdown图片自动上传到图床\nUsage of %s:\n", os.Args[0])
  3. flag.PrintDefaults()
  4. }
  1. ## 颜色输出
  2. 最简单的版本

package main

import “fmt”

func main() { fmt.Printf(“\033[1;31;40m%s\033[0m\n”,”Red.”) fmt.Printf(“\033[1;37;41m%s\033[0m\n”,”Red.”) }

  1. ![image-20220131124542690](https://cdn.nlark.com/yuque/0/2022/png/2976988/1646986811824-a4b056d2-dfaf-491a-a904-ac4bed912aa9.png)<br />输出所有颜色

package main

import “fmt”

func main() { for b := 40; b <= 47; b++ { // 背景色彩 = 40-47 for f := 30; f <= 37; f++ { // 前景色彩 = 30-37 for d := range []int{0, 1, 4, 5, 7, 8} { // 显示方式 = 0,1,4,5,7,8 fmt.Printf(“ %c[%d;%d;%dm%s(f=%d,b=%d,d=%d)%c[0m “, 0x1B, d, b, f, “”, f, b, d, 0x1B) } fmt.Println(“”) } fmt.Println(“”) } }

  1. ![image-20220131124701676](https://cdn.nlark.com/yuque/0/2022/png/2976988/1646986815339-6dfdc0ce-84c4-42b5-86ed-80bd23637a96.png)<br />但是每一次都这样很难记住,所以已经有人给他封装成了一个包:https://github.com/fatih/color,可以快速看下它的说明文档<br />**实例:**

package main

import ( “github.com/fatih/color” )

func main() { color.Blue(“aaaa%scccc”, “bbb”) color.Red(“red red”) color.Magenta(“And many others ..”) }

``` image-20220131125153876

参考