go语言常用标准库

go语言常用标准库

fmt

print和printn就不介绍了

fmt.Printf

printf是可以格式化输出,你可以想一想你学的c语言

主要讲一下占位符

package main

import "fmt"

func main() {
    name := "John"
    age := 28
    isMarried := false
    salary := 5000.5

    // 输出字符串,使用 %s
    fmt.Printf("His name is %s.\n", name) // His name is John.

    // 输出整数,使用 %d
    fmt.Printf("He is %d years old.\n", age) // He is 28 years old.

    // 输出布尔值,使用 %t
    fmt.Printf("Is he married? %t\n", isMarried) // Is he married? false

    // 输出浮点数,使用 %f
    fmt.Printf("His salary is %f.\n", salary) // His salary is 5000.5.

    // 使用 %v 会自动选择合适的格式
    fmt.Printf("His name is %v, he is %v years old, is he married? %v, his salary is %v.\n",
        name, age, isMarried, salary)
    // His name is John, he is 28 years old, is he married? false, his salary is 5000.5.

    // 使用 %+v 和 %#v 打印更详细的信息
    type Person struct {
        Name string
        Age  int
    }
    john := Person{Name: "John", Age: 28}
    fmt.Printf("John: %+v\n", john)  // John: {Name:John Age:28}
    fmt.Printf("John: %#v\n", john)  // John: main.Person{Name:"John", Age:28}

    // 使用 %T 打印变量的类型
    fmt.Printf("Type of john: %T\n", john) // Type of john: main.Person
}

Fprint

Fprint系列函数会将内容输出到一个io.Writer接口类型的变量w中,我们通常用这个函数往文件中写入内容。

package main

import (
    "fmt"
    "os"
)

func main() {
    f, err := os.Create("file.txt")
    if err != nil {
        fmt.Println(err)
        return
    }
    defer f.Close()

    name := "John"
    age := 28

    fmt.Fprint(f, "His name is ", name, ".")             // 写入到 file.txt: His name is John.
    fmt.Fprintln(f, "He is ", age, " years old.")        // 写入到 file.txt: He is 28 years old.\n
    fmt.Fprintf(f, "His name is %s, he is %d years old.", name, age)  // 写入到 file.txt: His name is John, he is 28 years old.
}

fmt.Fprint 系列函数也被广泛用于 HTTP 服务器的开发中,向客户端返回响应。以下是一个简单的 HTTP 服务器:

package main

import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    name := r.URL.Query().Get("name")
    if name == "" {
        name = "World"
    }

    // 使用 fmt.Fprintf 向 http.ResponseWriter 写入响应
    fmt.Fprintf(w, "Hello, %s!", name)
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

http.ResponseWriter 是满足 io.Writer 接口的,所以我们可以直接使用 fmt.Fprint 向其写入数据
在这里,当我们传入name参数时,就可以使用它去把我们传入的name写入到response
在这里插入图片描述

fmt.Scan

这个还是和c语言一样,这个是获取输入的

package main

import "fmt"

func main() {
	var (
		name    string
		age     int
		married bool
	)
	fmt.Scan(&name, &age, &married)
	fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married)
}

当然scanf就不讲了

Fscan

他就是和Fprint对应的
它就是从文件的读取数据了

package main

import (
    "fmt"
    "os"
)

func main() {
    file, err := os.Open("data.txt")
    if err != nil {
        fmt.Println("Error opening file:", err)
        return
    }
    defer file.Close()

    var name string
    var age int

    // Assume that data.txt contains lines in the format "name age"
    for {
        _, err := fmt.Fscan(file, &name, &age)
        if err != nil {
            if err == io.EOF {
                break // end of file reached
            }
            fmt.Println("Error reading file:", err)
            return
        }

        fmt.Printf("Name: %s, Age: %d\n", name, age)
    }
}

打开 data.txt 文件,然后在一个循环中使用 fmt.Fscan 读取并解析每一行的数据。

Time

时间类型

func timeDemo() {
    now := time.Now() //获取当前时间
    fmt.Printf("current time:%v\n", now)

    year := now.Year()     //年
    month := now.Month()   //月
    day := now.Day()       //日
    hour := now.Hour()     //小时
    minute := now.Minute() //分钟
    second := now.Second() //秒
    fmt.Printf("%d-%02d-%02d %02d:%02d:%02d\n", year, month, day, hour, minute, second)
}

时间戳

时间戳是自1970年1月1日(08:00:00GMT)至当前时间的总毫秒数。它也被称为Unix时间戳(UnixTimestamp)。

基于时间对象获取时间戳的示例代码如下:

func timestampDemo() {
    now := time.Now()            //获取当前时间
    timestamp1 := now.Unix()     //时间戳
    timestamp2 := now.UnixNano() //纳秒时间戳
    fmt.Printf("current timestamp1:%v\n", timestamp1)
    fmt.Printf("current timestamp2:%v\n", timestamp2)
}

使用time.Unix()函数可以将时间戳转为时间格式。

func timestampDemo2(timestamp int64) {
    timeObj := time.Unix(timestamp, 0) //将时间戳转为时间格式
    fmt.Println(timeObj)
    year := timeObj.Year()     //年
    month := timeObj.Month()   //月
    day := timeObj.Day()       //日
    hour := timeObj.Hour()     //小时
    minute := timeObj.Minute() //分钟
    second := timeObj.Second() //秒
    fmt.Printf("%d-%02d-%02d %02d:%02d:%02d\n", year, month, day, hour, minute, second)
}

时间操作

package main

import (
	"fmt"
	"time"
)

func main() {
	now := time.Now()
	fmt.Println("当前时间:", now)

	later := now.Add(time.Hour)
	fmt.Println("一小时后:", later)

	subtime := now.Sub(later)
	fmt.Println("时间差:", subtime)

	equal := now.Equal(later)
	fmt.Println("时间是否相等:", equal)

	before := now.Before(later)
	fmt.Println("现在是否早于一小时后:", before)

	// 计算当前时间与指定时间的时间差
	diff := now.Sub(time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC))
	fmt.Println("与2023年1月1日的时间差:", diff)
}

IO操作

输入输出

os.Stdin:标准输入的文件实例,类型为File
os.Stdout:标准输出的文件实例,类型为
File
os.Stderr:标准错误输出的文件实例,类型为*File

文件操作

func Create(name string) (file *File, err Error)
根据提供的文件名创建新的文件,返回一个文件对象,默认权限是0666
func NewFile(fd uintptr, name string) *File
根据文件描述符创建相应的文件,返回一个文件对象
func Open(name string) (file *File, err Error)
只读方式打开一个名称为name的文件
func OpenFile(name string, flag int, perm uint32) (file *File, err Error)
打开名称为name的文件,flag是打开的方式,只读、读写等,perm是权限
func (file *File) Write(b []byte) (n int, err Error)
写入byte类型的信息到文件
func (file *File) WriteAt(b []byte, off int64) (n int, err Error)
在指定位置开始写入byte类型的信息
func (file *File) WriteString(s string) (ret int, err Error)
写入string信息到文件
func (file *File) Read(b []byte) (n int, err Error)
读取数据到b中
func (file *File) ReadAt(b []byte, off int64) (n int, err Error)
从off开始读取数据到b中
func Remove(name string) Error
删除文件名为name的文件

打开和关闭文件
package main

import (
    "fmt"
    "os"
)

func main() {
    // 只读方式打开当前目录下的main.go文件
    file, err := os.Open("./main.go")
    if err != nil {
        fmt.Println("open file failed!, err:", err)
        return
    }
    // 关闭文件
    file.Close()
}
读写拷贝文件

写文件

package main

import (
    "fmt"
    "os"
)

func main() {
    // 新建文件
    file, err := os.Create("./xxx.txt")
    if err != nil {
        fmt.Println(err)
        return
    }
    defer file.Close()
    for i := 0; i < 5; i++ {
        file.WriteString("ab\n")
        file.Write([]byte("cd\n"))
    }
}

读文件

package main

import (
    "fmt"
    "io"
    "os"
)
func main() {
    // 打开文件
    file, err := os.Open("./xxx.txt")
    if err != nil {
        fmt.Println("open file err :", err)
        return
    }
    defer file.Close()
    // 定义接收文件读取的字节数组
    var buf [128]byte
    var content []byte
    for {
        n, err := file.Read(buf[:])
        if err == io.EOF {
            // 读取结束
            break
        }
        if err != nil {
            fmt.Println("read file err ", err)
            return
        }
        content = append(content, buf[:n]...)
    }
    fmt.Println(string(content))
}

拷贝文件

package main

import (
    "fmt"
    "io"
    "os"
)

func main() {
    // 打开源文件
    srcFile, err := os.Open("./xxx.txt")
    if err != nil {
        fmt.Println(err)
        return
    }
    // 创建新文件
    dstFile, err2 := os.Create("./abc2.txt")
    if err2 != nil {
        fmt.Println(err2)
        return
    }
    // 缓冲读取
    buf := make([]byte, 1024)
    for {
        // 从源文件读数据
        n, err := srcFile.Read(buf)
        if err == io.EOF {
            fmt.Println("读取完毕")
            break
        }
        if err != nil {
            fmt.Println(err)
            break
        }
        //写出去
        dstFile.Write(buf[:n])
    }
    srcFile.Close()
    dstFile.Close()
}

bufio

bufio 包实现了缓存I/O。它提供了bufio.Reader和bufio.Writer类型,其内部分别包装了io.Reader和io.Writer对象,同时分别实现了io.Reader和io.Writer接口。同时,该包为文本I/O提供了一些便利操作。

os.O_WRONLY	只写
os.O_CREATE	创建文件
os.O_RDONLY	只读
os.O_RDWR	读写
os.O_TRUNC	清空
os.O_APPEND	追加

bufio.Reader 类型

NewReader() 函数用于创建一个带缓冲的读取器,它从指定的 io.Reader 中读取数据并提供缓冲机制。
Reader 类型提供了 Read() 方法,用于从缓冲区读取数据,并在缓冲区为空时填充缓冲区。
示例:

data := []byte("Hello, World!")
reader := bufio.NewReader(bytes.NewReader(data))
buffer := make([]byte, 5)
for {
    n, err := reader.Read(buffer)
    if err != nil && err != io.EOF {
        fmt.Println("Error:", err)
        break
    }
    if n == 0 {
        break
    }
    fmt.Println(string(buffer[:n]))
}

bufio.Writer

NewWriter() 函数用于创建一个缓冲写入器,它将数据写入指定的 io.Writer。
Writer 类型提供了 Write() 方法,用于将数据写入缓冲区,并在缓冲区满或显式刷新时将数据写入底层的 io.Writer。
示例:

file, _ := os.Create("output.txt")
writer := bufio.NewWriter(file)

text := "Hello, World!"
writer.WriteString(text)
writer.Flush() // 刷新缓冲区,确保所有数据被写入底层的文件

file.Close()

bufio.Scanner

NewScanner() 函数用于创建一个缓冲读取器,它从指定的 io.Reader 中读取数据。
Scanner 类型提供了方便的方法来逐行或逐个词读取数据。
示例:

file, _ := os.Open("data.txt")
scanner := bufio.NewScanner(file)

for scanner.Scan() {
    line := scanner.Text()
    fmt.Println(line)
}

if err := scanner.Err(); err != nil {
    fmt.Println("Error:", err)
}

Strconv

这个库就比较简单了,因为它主要就是用来我们的类型转换

string与int类型转换

Atoi()

Atoi()函数用于将字符串类型的整数转换为int类型 如果传入的字符串参数无法转换为int类型,就会返回错误。

s1 := "100"
i1, err := strconv.Atoi(s1)
if err != nil {
    fmt.Println("can't convert to int")
} else {
    fmt.Printf("type:%T value:%#v\n", i1, i1) //type:int value:100
}
Itoa()

Itoa()函数用于将int类型数据转换为对应的字符串表示

i2 := 200
s2 := strconv.Itoa(i2)
fmt.Printf("type:%T value:%#v\n", s2, s2) //type:string value:"200"

Parse系列函数

Parse类函数用于转换字符串为给定类型的值:ParseBool()、ParseFloat()、ParseInt()、ParseUint()。

ParseBool()

ParseBool() 函数用于将字符串解析为布尔值。它接受一个字符串参数,该字符串必须是 “true”、“false”、“1” 或 “0”。

package main

import (
	"fmt"
	"strconv"
)

func main() {
	str := "true"
	boolValue, err := strconv.ParseBool(str)
	if err != nil {
		fmt.Println("解析错误:", err)
	} else {
		fmt.Println("解析的布尔值为:", boolValue)
	}
}

下面的我就不举例子了,就和这个一样的

ParseFloat()

这个就是转为浮点数

str := "3.14"
	floatValue, err := strconv.ParseFloat(str, 64)

第二个参数 64 指定浮点数的位数,这里解析为 float64。

ParseInt()

package main

import (
	"fmt"
	"strconv"
)

func main() {
	str := "123"
	intValue, err := strconv.ParseInt(str, 10, 64)
	if err != nil {
		fmt.Println("解析错误:", err)
	} else {
		fmt.Println("解析的整数为:", intValue)
	}
}

可以选择进制和int类型

Format系列函数

Format就是格式化的意思
什么叫做格式化
比如我举bool这个类型的例子
我bool的表示方式可以是false,ture,1,0
但是格式化后我的1,0都用false和ture表示

Http和URL

Http其实是在net库中的其中之一

Http提供了我们http服务端和客户端的实现
然后在这里简单讲讲URl库在http服务发挥的作用
你可以使用url.Values来构建查询字符串,并使用url.Path和url.RawQuery来构建完整的URL

package main

import (
    "fmt"
    "net/url"
)

func main() {
    // 创建一个url.Values实例
    params := url.Values{}
    params.Add("key1", "value1")
    params.Add("key2", "value2")

    // 使用Encode方法将其转换为查询字符串
    queryStr := params.Encode()
    fmt.Println(queryStr) // 输出: "key1=value1&key2=value2"

    // 构建完整的URL
    basePath := "https://example.com/path"
    fullUrl := basePath + "?" + queryStr
    fmt.Println(fullUrl) // 输出: "https://example.com/path?key1=value1&key2=value2"
}

看了这个例子应该能够明白

Http客户端

发送请求

http.Get(url string) (*http.Response, error): 发送一个GET请求到指定的URL。

http.NewRequest(method, url string, body io.Reader) (*http.Request, error): 创建一个新的HTTP请求。

http.Do(req *http.Request) (*http.Response, error): 执行一个HTTP请求,并返回响应。

处理响应

resp.Body: 响应体,可以使用

ioutil.ReadAll(resp.Body)来读取。

resp.Status: 响应的状态行(例如:“200 OK”)。

resp.Header: 响应的HTTP头。

设置请求头和客户端参数

req.Header.Set(key, value): 设置请求头的值。

req.URL.Path: 设置请求的URL路径。

req.URL.RawQuery: 设置请求的查询字符串。

get请求和响应

我直接举个例子,然后来讲解

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "net/url"
)

func main() {
    // 创建一个url.Values实例,设定立了我们查询的参数
    params := url.Values{}
    params.Add("key1", "value1")
    params.Add("key2", "value2")

    // 使用Encode方法将其转换为查询字符串
    queryStr := params.Encode()

    // 构建完整的URL
    basePath := "https://example.com/path"
    fullUrl := basePath + "?" + queryStr

    // 发送GET请求
    resp, err := http.Get(fullUrl)
    if err != nil {
        fmt.Println("Error making request:", err)
        return
    }
    defer resp.Body.Close()

    // 读取并打印响应体
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("Error reading response body:", err)
        return
    }
     // 打印响应体
    fmt.Println("Response body:", string(body))

    // 打印响应状态
    fmt.Println("Response status:", resp.Status)

    // 打印响应头
    fmt.Println("Response headers:", resp.Header)
}
post请求和响应
package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
)

func main() {
	// 创建表单数据
	formData := url.Values{
		"key1": {"value1"},
		"key2": {"value2"},
	}

	// 创建请求体
	body := bytes.NewBufferString(formData.Encode())

	// 发送POST请求
	resp, err := http.Post("http://example.com/resource", "application/x-www-form-urlencoded", body)//三个参数,第一个是请求的url,第二个是type,第三个是请求头,也就是我们的参数和参数值
	if err != nil {
		fmt.Println("请求失败:", err)
		return
	}
	defer resp.Body.Close()

	// 读取响应体
	responseBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("读取响应失败:", err)
		return
	}

	  // 打印响应体
    fmt.Println("Response body:", string(body))

    // 打印响应状态
    fmt.Println("Response status:", resp.Status)

    // 打印响应头
    fmt.Println("Response headers:", resp.Header)
}

服务端

对应的客户端写好了,思考我们怎么写服务端呢
无疑需要实现下面几个功能
启动服务器 – 接收请求 – 处理请求 – 返回处理结果

设置路由和处理函数

http.HandleFunc(pattern string, handler http.HandlerFunc): 注册一个路由和处理函数。

http.Handle(pattern string, handler http.Handler): 注册一个路由和处理器,适用于各种类型的HTTP处理函数。

启动服务器

http.ListenAndServe(addr string, handler http.Handler) error: 监听并服务指定的地址(如:“localhost:8080”)。

http.ListenAndServeTLS(addr, certFile, keyFile string, handler http.Handler) error: 类似于ListenAndServe,但用于HTTPS。

处理请求

中间件是在请求处理前后添加额外功能的函数。

http.HandlerFunc: 一个接受两个参数(http.ResponseWriter和http.Request)并返回一个http.Handler的函数。

实例分析

package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/resource", func(w http.ResponseWriter, r *http.Request) {
        // 接收请求
        body, err := ioutil.ReadAll(r.Body)
        defer r.Body.Close()
        if err != nil {
            http.Error(w, "Error reading request body", http.StatusInternalServerError)
            return
        }

        //处理请求
        fmt.Println("Received request with body:", string(body))

        //返回结果
        w.Write([]byte("OK"))
    })
		//启动服务器
    fmt.Println("Starting server on port 8080")
    http.ListenAndServe(":8080", nil)
}

看起来还是比较简单的

数据处理

我们知道交互的时候可不是数据原封不动的,一般都要转为其他的格式
常见的就是json,xml,二进制

JSON

编码
json使用go语言内置的encoding/json 标准库
编码json使用json.Marshal()函数可以对一组数据进行JSON格式的编码

package main

import (
	"encoding/json"
	"fmt"
	"log"
)

// 定义一个结构体,用于表示一个人
type Person struct {
	Name   string `json:"name"`
	Age    int    `json:"age"`
	Email  string `json:"email"`
}

func main() {
	// 创建一个Person实例
	p := Person{Name: "张三", Age: 30, Email: "zhangsan@example.com"}

	// 使用json.Marshal对Person实例进行编码
	data, err := json.Marshal(p)
	if err != nil {
		log.Fatal("JSON marshaling failed: ", err)
	}

	// 输出编码后的JSON字符串
	fmt.Println(string(data))//{"name":"张三","age":30,"email":"zhangsan@example.com"}
}

解码

使用json.Unmarshal()函数可以对一组数据进行JSON格式的解码

package main

import (
	"encoding/json"
	"fmt"
	"log"
)

// 定义一个结构体,用于表示一个人
type Person struct {
	Name  string `json:"name"`
	Age   int    `json:"age"`
	Email string `json:"email"`
}

func main() {
	// 假设我们有一个JSON格式的字符串
	jsonData := `{"name":"张三","age":30,"email":"zhangsan@example.com"}`

	// 创建一个Person实例,用于存储解码后的数据
	var p Person

	// 使用json.Unmarshal对JSON数据进行解码
	err := json.Unmarshal([]byte(jsonData), &p)
	if err != nil {
		log.Fatal("JSON unmarshaling failed: ", err)
	}

	// 输出解码后的Person实例的字段
	fmt.Printf("Name: %s\n", p.Name)
	fmt.Printf("Age: %d\n", p.Age)
	fmt.Printf("Email: %s\n", p.Email)
}

输出
Name: 张三
Age: 30
Email: zhangsan@example.com

XML

在Go语言中,处理XML数据同样简单,可以使用encoding/xml标准库来实现。这个库提供了Marshal和Unmarshal函数,用于XML数据的编码和解码。

XML编码(Marshal)

package main

import (
	"encoding/xml"
	"fmt"
	"os"
)

// Person 结构体定义
type Person struct {
	Name   string `xml:"name"`
	Age    int    `xml:"age"`
	Email  string `xml:"email"`
}

func main() {
	// 创建一个Person实例
	p := Person{Name: "张三", Age: 30, Email: "zhangsan@example.com"}

	// 使用xml.Marshal对Person实例进行编码
	data, err := xml.Marshal(p)
	if err != nil {
		fmt.Println("XML marshaling failed:", err)
		return
	}

	// 输出编码后的XML字符串
	fmt.Println(string(data))

	// 为了格式化输出,可以使用xml.MarshalIndent
	data, err = xml.MarshalIndent(p, " ", "  ")
	if err != nil {
		fmt.Println("XML marshaling failed:", err)
		return
	}

	// 将格式化的XML输出到标准输出
	fmt.Println(string(data))
}

XML解码(Unmarshal)

package main

import (
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"os"
)

// Person 结构体定义
type Person struct {
	Name   string `xml:"name"`
	Age    int    `xml:"age"`
	Email  string `xml:"email"`
}

func main() {
	// 假设我们有一个XML格式的字符串
	xmlData := `<Person><name>张三</name><age>30</age><email>zhangsan@example.com</email></Person>`

	// 使用xml.Unmarshal对XML数据进行解码
	var p Person
	err := xml.Unmarshal([]byte(xmlData), &p)//接收两个变量,一个是xml数据但是要切片,一个是接收对象
	if err != nil {
		fmt.Println("XML unmarshaling failed:", err)
		return
	}

	// 输出解码后的Person实例的字段
	fmt.Printf("Name: %s\n", p.Name)
	fmt.Printf("Age: %d\n", p.Age)
	fmt.Printf("Email: %s\n", p.Email)
}

MSGPack

它相比于xml和json,更快,是一种高效的二进制序列化格式

但是需要安装

go get github.com/vmihailenco/msgpack/v5
package main

import (
	"fmt"
	"github.com/vmihailenco/msgpack/v5"
)

// Person 结构体定义
type Person struct {
	Name   string
	Age    int
	Email  string
}

func main() {
	// 创建一个Person实例
	p := Person{Name: "张三", Age: 30, Email: "zhangsan@example.com"}

	// 使用msgpack.Marshal对Person实例进行编码
	data, err := msgpack.Marshal(p)
	if err != nil {
		fmt.Println("MSGPack marshaling failed:", err)
		return
	}

	// 使用msgpack.Unmarshal对MSGPack数据进行解码
	var p2 Person
	err = msgpack.Unmarshal(data, &p2)
	if err != nil {
		fmt.Println("MSGPack unmarshaling failed:", err)
		return
	}

	// 输出解码后的Person实例的字段
	fmt.Printf("Name: %s\n", p2.Name)
	fmt.Printf("Age: %d\n", p2.Age)
	fmt.Printf("Email: %s\n", p2.Email)
}

我们首先使用msgpack.Marshal()函数将Person实例编码为MessagePack格式的数据。然后,我们使用msgpack.Unmarshal()函数将这些数据解码回一个新的Person实例p2。msgpack.Unmarshal()函数接受两个参数:第一个是要解码的字节切片,第二个是一个指向要填充数据的变量的指针。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值