golang基础(3)

简介: golang基础

golang基础(2)https://developer.aliyun.com/article/1530652

格式化

package main
import "fmt"
type point struct {
  x, y int
}
func main() {
  s := "hello"
  n := 123
  p := point{1, 2}
  fmt.Println(s, n) // hello 123
  fmt.Println(p)    // {1 2}
  fmt.Printf("s=%v\n", s)  // s=hello
  fmt.Printf("n=%v\n", n)  // n=123
  fmt.Printf("p=%v\n", p)  // p={1 2}
  fmt.Printf("p=%+v\n", p) // p={x:1 y:2}
  fmt.Printf("p=%#v\n", p) // p=main.point{x:1, y:2}
  f := 3.141592653
  fmt.Println(f)          // 3.141592653
  fmt.Printf("%.2f\n", f) // 3.14
}

json

package main
import (
  "encoding/json"
  "fmt"
)
type userInfo struct {
  Name  string
  Age   int `json:"age"`
  Hobby []string
}
func main() {
  a := userInfo{Name: "wang", Age: 18, Hobby: []string{"Golang", "TypeScript"}}
  buf, err := json.Marshal(a)
  if err != nil {
    panic(err)
  }
  fmt.Println(buf)         // [123 34 78 97...]
  fmt.Println(string(buf)) // {"Name":"wang","age":18,"Hobby":["Golang","TypeScript"]}
  buf, err = json.MarshalIndent(a, "", "\t")
  if err != nil {
    panic(err)
  }
  fmt.Println(string(buf))
  var b userInfo
  err = json.Unmarshal(buf, &b)
  if err != nil {
    panic(err)
  }
  fmt.Printf("%#v\n", b) // main.userInfo{Name:"wang", Age:18, Hobby:[]string{"Golang", "TypeScript"}}
}

json.MarshalIndent作用

ChatGPT

json.MarshalIndent 是 Go 语言标准库中用于将数据结构序列化为 JSON 格式并添加缩进的函数。它将 Go 的数据结构转换为 JSON 字节切片,并根据指定的缩进格式对 JSON 进行格式化,使 JSON 数据在显示时更易读。

函数签名:

goCopy code
func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
  • v: 要序列化为 JSON 的数据结构,通常为一个 Go 的数据类型,例如 struct、map、slice 等。
  • prefix: 缩进前缀,用于在每一行缩进级别之前添加的前缀字符串。一般设置为空格或制表符来实现缩进效果。
  • indent: 每一行缩进的字符串,通常由空格或制表符组成。

json.MarshalIndent 会根据 v 中的数据结构生成一个带有缩进格式的 JSON 字节切片。

示例:

goCopy codepackage main
import (
  "encoding/json"
  "fmt"
)
type Person struct {
  Name    string
  Age     int
  Country string
}
func main() {
  person := Person{
    Name:    "John",
    Age:     30,
    Country: "USA",
  }
  // 使用 json.MarshalIndent 将结构体序列化为带有缩进格式的 JSON
  jsonData, err := json.MarshalIndent(person, "", "    ")
  if err != nil {
    fmt.Println("Error marshaling JSON:", err)
    return
  }
  fmt.Println(string(jsonData))
}

在上面的例子中,我们定义了一个 Person 结构体,然后使用 json.MarshalIndent 将其序列化为带有缩进格式的 JSON。输出结果将是类似于下面的内容:

jsonCopy code{
    "Name": "John",
    "Age": 30,
    "Country": "USA"
}

这样的格式化使得生成的 JSON 数据更具可读性,并且更容易在调试和查看 JSON 数据时进行理解。

time

package main
import (
  "fmt"
  "time"
)
func main() {
  now := time.Now()
  fmt.Println(now) // 2022-03-27 18:04:59.433297 +0800 CST m=+0.000087933
  t := time.Date(2022, 3, 27, 1, 25, 36, 0, time.UTC)
  t2 := time.Date(2022, 3, 27, 2, 30, 36, 0, time.UTC)
  fmt.Println(t)                                                  // 2022-03-27 01:25:36 +0000 UTC
  fmt.Println(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute()) // 2022 March 27 1 25
  fmt.Println(t.Format("2006-01-02 15:04:05"))                    // 2022-03-27 01:25:36
  diff := t2.Sub(t)
  fmt.Println(diff)                           // 1h5m0s
  fmt.Println(diff.Minutes(), diff.Seconds()) // 65 3900
  t3, err := time.Parse("2006-01-02 15:04:05", "2022-03-27 01:25:36")
  if err != nil {
    panic(err)
  }
  fmt.Println(t3 == t)    // true
  fmt.Println(now.Unix()) // 1648738080
}

字符串转换

package main
import (
  "fmt"
  "strconv"
)
func main() {
  f, _ := strconv.ParseFloat("1.234", 64)
  fmt.Println(f) // 1.234
  n, _ := strconv.ParseInt("111", 10, 64)
  fmt.Println(n) // 111
  n, _ = strconv.ParseInt("0x1000", 0, 64)
  fmt.Println(n) // 4096
  n2, _ := strconv.Atoi("123")
  fmt.Println(n2) // 123
  n2, err := strconv.Atoi("AAA")
  fmt.Println(n2, err) // 0 strconv.Atoi: parsing "AAA": invalid syntax
}

env

package main
import (
  "fmt"
  "os"
  "os/exec"
)
func main() {
  // go run example/20-env/main.go a b c d
  fmt.Println(os.Args)           // [/var/folders/8p/n34xxfnx38dg8bv_x8l62t_m0000gn/T/go-build3406981276/b001/exe/main a b c d]
  fmt.Println(os.Getenv("PATH")) // /usr/local/go/bin...
  fmt.Println(os.Setenv("AA", "BB"))
  buf, err := exec.Command("grep", "127.0.0.1", "/etc/hosts").CombinedOutput()
  if err != nil {
    panic(err)
  }
  fmt.Println(string(buf)) // 127.0.0.1       localhost
}

协程

cpu本身可以保存状态,且不需要切换

实战

猜数游戏

package main
import (
  "bufio"
  "fmt"
  "math/rand"
  "os"
  "strconv"
  "strings"
  "time"
)
func main() {
  maxNum := 100
  rand.Seed(time.Now().UnixNano())
  secretNumber := rand.Intn(maxNum)
  fmt.Println("the secret is", secretNumber)
  fmt.Println("please input your guess")
  //把输入文件转成一个只读的流
  reader := bufio.NewReader(os.Stdin)
  //读取用户输入,直到遇到换行符为止
  for {
    input, err := reader.ReadString('\n')
    if err != nil {
      fmt.Println("an error occured while reading input , Please try again", err)
      continue
    }
    input = strings.TrimSuffix(input, "\r\n")
    guess, err := strconv.Atoi(input)
    if err != nil {
      fmt.Println("Invaild input", err)
      continue
    }
    fmt.Println("Your gusee is", guess)
    if guess > secretNumber {
      fmt.Println("your input is bugger ")
    } else if guess < secretNumber {
      fmt.Println("your input is smaller")
    } else {
      fmt.Println("correct")
      break
    }
  }
}

是的,Go标准库中还有一些与字符串处理相关的函数,其中一些与 strings.TrimSuffix 类似,用于处理字符串的前缀和后缀。以下是其中几个常用的函数:

  1. strings.TrimPrefix(s, prefix string) string: 去除字符串开头的指定前缀,返回新的字符串。如果原始字符串以指定前缀开头,则去除该前缀;否则,原始字符串保持不变。
  2. strings.HasPrefix(s, prefix string) bool: 检查字符串是否以指定前缀开头,返回一个布尔值。如果字符串以指定前缀开头,返回 true,否则返回 false
  3. strings.HasSuffix(s, suffix string) bool: 检查字符串是否以指定后缀结尾,返回一个布尔值。如果字符串以指定后缀结尾,返回 true,否则返回 false
  4. strings.Trim(s string, cutset string) string: 去除字符串开头和结尾的指定字符集合(cutset)中包含的字符,返回新的字符串。如果 cutset 为空,则会去除字符串开头和结尾的空白字符。
  5. strings.TrimSpace(s string) string: 去除字符串开头和结尾的空白字符,返回新的字符串。

这些函数在处理字符串时非常有用,特别是在需要对字符串进行预处理或清理时。使用这些函数可以使字符串处理代码更加简洁和易读。记住,在处理字符串时,要注意处理 Unicode 字符和特殊情况,以确保代码的正确性和鲁棒性。

网络请求

package main
import (
  "bytes"
  "encoding/json"
  "fmt"
  "os"
  "io"
  "log"
  "net/http"
)
type AutoGenerated struct {
  Rc   int `json:"rc"`
  Wiki struct {
  } `json:"wiki"`
  Dictionary struct {
    Entry        string        `json:"entry"`
    Explanations []string      `json:"explanations"`
    Related      []interface{} `json:"related"`
    Source       string        `json:"source"`
    Prons        struct {
    } `json:"prons"`
    Type string `json:"type"`
  } `json:"dictionary"`
}
type DictRequest struct {
  TransType string `json:"trans_type"`
  Source    string `json:"source"`
  UserId    string `json:"user_id"`
}
func main() {
  if len(os.Args) != 2 {
    fmt.Fprint(os.Stderr, `usage: simpleDict WORD
    example:simpleDict hellp`)
    os.Exit(1)
  }
  word := os.Args[1]
  query(word)
}
func query(word string) {
  client := &http.Client{}
  // var data = strings.NewReader(`{"trans_type":"zh2en","source":"你好"}`)
  request := DictRequest{TransType: "zh2en", Source: word}
  buf, err := json.Marshal(request)
  if err != nil {
    log.Fatal(err)
  }
  //因为json.Marshal返回的是一个byte数组
  var data = bytes.NewReader(buf)
  //因为这个参数可能是从文件读取的可能很大很大,所以需要是流
  req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data)
  if err != nil {
    log.Fatal(err)
  }
  req.Header.Set("authority", "api.interpreter.caiyunai.com")
  req.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36")
  req.Header.Set("app-name", "xy")
  req.Header.Set("content-type", "application/json;charset=UTF-8")
  req.Header.Set("accept", "application/json, text/plain, */*")
  req.Header.Set("device-id", "9395fef18b8c40f79517da2f52a54705")
  req.Header.Set("os-type", "web")
  req.Header.Set("x-authorization", "token:qgemv4jr1y38jyq6vhvi")
  req.Header.Set("origin", "https://fanyi.caiyunapp.com")
  req.Header.Set("sec-fetch-site", "cross-site")
  req.Header.Set("sec-fetch-mode", "cors")
  req.Header.Set("sec-fetch-dest", "empty")
  req.Header.Set("referer", "https://fanyi.caiyunapp.com/")
  req.Header.Set("accept-language", "zh-CN,zh;q=0.9")
  resp, err := client.Do(req)
  if err != nil {
    log.Fatal(err)
  }
  //关闭流不然会泄露,
  defer resp.Body.Close()
  //得到的bodytext是字节数组
  bodyText, err := io.ReadAll(resp.Body)
  if err != nil {
    log.Fatal(err)
  }
  if resp.StatusCode != 200 {
    log.Fatal("bad status", resp.StatusCode, "body", string(bodyText))
  }
  //字符串输出
  // fmt.Printf("%s\n", bodyText)
  var dicresponce AutoGenerated
  err = json.Unmarshal(bodyText, &dicresponce)
  if err != nil {
    log.Fatal(err)
  }
  fmt.Printf("%#v\n", dicresponce)
}

这是一个简单的函数 process,它接受一个网络连接 conn 作为参数,并对这个连接进行读取和写入操作。让我们逐步解析这个函数:

  1. func process(conn net.Conn) { 定义了一个名为 process 的函数,它接受一个 net.Conn 类型的参数 conn,该参数代表网络连接。
  2. defer conn.Close() 使用 defer 关键字延迟执行 conn.Close(),确保在函数执行完毕后关闭网络连接。defer 关键字会使 conn.Close()process 函数的末尾执行,无论函数是正常返回还是因为错误而退出,都会执行该语句来关闭连接。
  3. reader := bufio.NewReader() 创建一个 bufio.Reader 类型的对象 reader,用于从网络连接中读取数据。但在这里,创建 bufio.Reader 时没有传递参数,因此这个 reader 并未与指定的网络连接 conn 关联,应该修改为 reader := bufio.NewReader(conn)
  4. for { 进入一个无限循环,不断从 reader 中读取字节并将其写入连接 conn
  5. b, err := reader.ReadByte() 使用 ReadByte() 方法从 reader 中读取一个字节。ReadByte() 返回两个值,一个是读取的字节 b,另一个是可能出现的错误 err
  6. if err != nil { break } 检查读取操作是否发生错误,如果出现错误,退出循环,跳出 for 循环。
  7. _, err = conn.Write([]byte{b}) 将刚刚读取的字节 b 通过 conn.Write() 方法写入连接 connWrite() 方法返回两个值,一个是写入的字节数,另一个是可能出现的错误 err
  8. if err != nil { break } 检查写入操作是否发生错误,如果出现错误,退出循环,跳出 for 循环。
  9. } 循环会持续进行,不断读取字节并将其写入连接,直到发生读取或写入错误,导致循环终止。

总体来说,这个函数的目的是将从网络连接中读取的数据逐字节原样写回同一个连接。它将连接作为参数传递,然后在一个无限循环中读取连接的内容,并将每个字节再写回该连接。当读取或写入操作发生错误时,函数会关闭连接并终止。注意在修改 bufio.NewReader()bufio.NewReader(conn) 之后,这个函数将能够正常地工作。

在 Go 语言中,defer 关键字用于延迟(defer)函数的执行,使函数在当前函数执行完成后才会被调用。无论函数是正常返回还是遇到错误导致异常退出,defer 关键字都会确保它指定的函数会被执行,类似于其他编程语言中的 “finally” 块。

defer 的作用如下:

  1. 延迟函数的执行:使用 defer 关键字可以将函数调用推迟到包含 defer 语句的函数返回之后执行。这在需要确保某些资源在函数执行完毕后得到释放时非常有用,例如关闭文件句柄、释放锁、关闭数据库连接等。
  2. 逆序执行:如果一个函数中有多个 defer 语句,它们会按照后进先出(LIFO)的顺序执行,即最后一个 defer 语句会最先执行,而第一个 defer 语句会最后执行。
  3. 避免忘记资源释放:使用 defer 可以帮助避免因为遗漏释放资源而导致的内存泄漏或其他资源泄漏问题。由于 defer 会在函数退出时执行,因此可以确保在函数执行完毕后及时释放资源。

示例:

goCopy codepackage main
import (
  "fmt"
  "os"
)
func main() {
  file, err := os.Open("example.txt")
  if err != nil {
    fmt.Println("Error opening file:", err)
    return
  }
  defer file.Close() // 在函数返回时关闭文件
  // 使用文件进行一些操作,比如读取数据等
  // 函数执行完毕时,defer语句会执行,文件会被关闭
}

在上面的例子中,通过 defer file.Close(),无论函数是否正常返回,file.Close() 都会在函数返回时被调用,确保文件句柄被及时关闭。

总结:defer 是 Go 语言中一种方便的机制,用于处理资源释放、清理等操作,使得代码更加清晰、健壮,同时避免了忘记释放资源的问题。

io.ReadAl

io.ReadAll 是 Go 语言标准库中的一个函数,它的作用是从输入流(io.Reader)中读取所有数据并返回一个字节切片([]byte)表示读取的内容。

函数签名:

goCopy code
func ReadAll(r io.Reader) ([]byte, error)

参数 r 是一个实现了 io.Reader 接口的对象,可以是文件、网络连接、内存缓冲区等等。io.Reader 接口包含了读取数据的基本方法。

io.ReadAll 会读取 r 中的所有数据,直到遇到文件结束符(EOF)为止,并将读取的内容存储在一个字节切片中返回。同时,它也会返回可能出现的错误(如果有的话)。

使用 io.ReadAll 的常见场景是读取小文件或读取来自网络连接等的数据。请注意,对于非常大的数据流,io.ReadAll 可能不是最佳的选择,因为它会将整个数据流读取到内存中,可能导致内存消耗较大。在处理大型数据流时,最好使用逐块读取的方式。

示例:

goCopy codepackage main
import (
  "fmt"
  "io"
  "os"
)
func main() {
  file, err := os.Open("example.txt")
  if err != nil {
    fmt.Println("Error opening file:", err)
    return
  }
  defer file.Close()
  data, err := io.ReadAll(file)
  if err != nil {
    fmt.Println("Error reading file:", err)
    return
  }
  fmt.Println("File contents:")
  fmt.Println(string(data))
}

在上面的例子中,我们打开一个名为 “example.txt” 的文件,并使用 io.ReadAll 将文件的所有内容读取到 data 变量中,最后打印出文件的内容。

socket5代理

golang基础(4)https://developer.aliyun.com/article/1530658

相关文章
|
10月前
|
大数据 编译器 Go
104.【GoLang基础】(三)
104.【GoLang基础】
68 0
|
10月前
|
存储 编译器 Go
104.【GoLang基础】(七)
104.【GoLang基础】
45 0
|
10月前
|
缓存 并行计算 Go
104.【GoLang基础】(四)
104.【GoLang基础】
39 0
|
10月前
|
编译器 Go Windows
104.【GoLang基础】(一)
104.【GoLang基础】
37 0
|
10月前
|
Java 编译器 Go
104.【GoLang基础】(二)
104.【GoLang基础】
38 0
|
24天前
|
Go
|
24天前
|
监控 安全 Go
|
24天前
|
存储 Java Go
|
24天前
|
存储 Java Go
|
8月前
|
中间件 Go API