Golang文件操作

文章目錄

  • 文件操作
    • 基本介紹
    • 普通的文件操作方式(os包)
    • 帶緩沖的文件操作方式(bufio包)
    • 文件拷貝操作(io包)
  • 命令行參數
    • 基本介紹
    • 解析命令行參數(flag包)
  • JSON
    • 基本介紹
    • JSON序列化
    • JSON反序列化

文件操作

基本介紹

基本介紹

  • 文件操作是指對計算機文件進行讀取、寫入、修改、刪除和移動等操作的過程,它可以用于讀取配置文件、存儲日志、處理用戶上傳的文件等,Go中主要通過os和bufio包提供文件操作功能。
  • 文件在程序中是以流的形式進行操作的,我們把數據在數據源(文件)和程序(內存)之間經歷的路徑叫做流。其中數據從數據源到程序的路徑叫做輸入流,數據從程序到數據源的路徑叫做輸出流。

文件流示意圖如下:

在這里插入圖片描述

普通的文件操作方式(os包)

os包介紹

在os包中,File類型代表一個打開的文件,其封裝了與文件相關的操作和屬性。File結構體的定義如下:

type File struct {*file // os specific
}

File結構體中以*type的方式嵌套了file類型的匿名結構體指針,實際文件的屬性信息都存儲在file結構體中。file結構體的定義如下:

type file struct {pfd         poll.FDname        stringdirinfo     atomic.Pointer[dirInfo] // nil unless directory being readnonblock    bool                    // whether we set nonblocking modestdoutOrErr bool                    // whether this is stdout or stderrappendMode  bool                    // whether file is opened for appending
}

file結構體各字段說明:

  • pfd:用于與底層的操作系統文件描述符進行交互。
  • name:表示文件的名稱(包括路徑)。
  • dirinfo:用于在讀取目錄時緩存目錄的信息(打開的文件是目錄時被使用)。
  • nonblock:表示文件是否設置為非阻塞模式。
  • stdoutOrErr:表示文件是否是標準輸出或標準錯誤。
  • appendMode:表示文件是否以追加模式打開。

每一個打開的文件都對應一個文件描述符,file結構體中的pfd是poll.FD類型的,實際文件對應的文件描述符就存儲在poll.FD結構體的Sysfd字段中。FD結構體的定義如下:

type FD struct {// Lock sysfd and serialize access to Read and Write methods.fdmu fdMutex// System file descriptor. Immutable until Close.Sysfd int// Platform dependent state of the file descriptor.SysFile// I/O poller.pd pollDesc// Semaphore signaled when file is closed.csema uint32// Non-zero if this file has been set to blocking mode.isBlocking uint32// Whether this is a streaming descriptor, as opposed to a// packet-based descriptor like a UDP socket. Immutable.IsStream bool// Whether a zero byte read indicates EOF. This is false for a// message based socket connection.ZeroReadIsEOF bool// Whether this is a file rather than a network socket.isFile bool
}

打開文件

在os包中,使用OpenFile函數打開文件,該函數的函數原型如下:

func OpenFile(name string, flag int, perm FileMode) (file *File, err error)

參數說明:

  • name:表示需要打開的文件名稱(包括路徑)。
  • flag:表示打開文件的方式。
  • perm:表示新創建文件的權限,通常設置為0666(表示任何人都可讀寫,不可執行)。

返回值說明:

  • file:如果打開文件成功,將返回文件對應的File結構體。
  • err:如果打開文件過程中出錯,將返回非nil的錯誤值。

打開文件的方式可以使用以下標注之一或它們的組合。如下:

參數選項含義
O_RDONLY以只讀方式打開文件
O_WRONLY以只寫方式打開文件
O_RDWR以讀寫方式打開文件
O_APPEND以追加的方式打開文件
O_CREATE如果文件不存在,則創建文件
O_EXCL與O_CREATE一起使用,確保創建新文件時不會覆蓋現有文件
O_SYNC在每次寫入操作后同步文件內容到磁盤
O_TRUNC如果文件已存在,將截斷文件為零長度

打開文件示例如下:

package mainimport ("fmt""os"
)func main() {name := `D:\github\Golang-topics\src\go_code\FileOperation\FileOperation\NormalOperation\data.txt`// 打開文件file, err := os.OpenFile(name, os.O_WRONLY|os.O_CREATE, 0666)if err != nil {fmt.Printf("open file error, err = %v\n", err)return}fmt.Printf("open file success, fd = %v\n", file.Fd()) // open file success, fd = 420
}

說明一下:

  • 通過File結構體的Fd方法,可以獲取該文件對應的文件描述符。文件的文件描述符由底層操作系統分配,每次打開文件時分配的文件描述符可能不同。

關閉文件

在os包中,使用File結構體的Close方法關閉文件,該方法的原型如下:

func (f *File) Close() error

返回值說明:

  • 關閉文件成功返回nil,否則返回非nil的錯誤值。

關閉文件示例如下:

package mainimport ("fmt""os"
)func main() {name := `D:\github\Golang-topics\src\go_code\FileOperation\FileOperation\NormalOperation\data.txt`// 1、打開文件file, err := os.OpenFile(name, os.O_WRONLY|os.O_CREATE, 0666)if err != nil {fmt.Printf("open file error, err = %v\n", err)return}// 2、延遲關閉文件defer file.Close()
}

說明一下:

  • 文件操作完畢后需要及時調用Close方法對文件進行關閉,避免造成文件描述符泄露。
  • 通常利用defer機制對文件進行延遲關閉,在defer語句之后仍然可以操作文件,文件將會在函數執行完畢后自動關閉。

獲取文件屬性信息

在os包中,使用File結構體的Stat方法獲取文件的屬性信息,該方法的原型如下:

func (f *File) Stat() (fi FileInfo, err error)

返回值說明:

  • fi:如果方法調用成功,將返回文件的屬性信息。
  • err:如果方法調用過程中出錯,將返回非nil的錯誤值。

Stat方法獲取到的文件信息FileInfo是一個接口類型,該類型的定義如下:

type FileInfo interface {Name() string       // base name of the fileSize() int64        // length in bytes for regular files; system-dependent for othersMode() FileMode     // file mode bitsModTime() time.Time // modification timeIsDir() bool        // abbreviation for Mode().IsDir()Sys() any           // underlying data source (can return nil)
}

FileInfo接口中各方法說明:

  • Name方法:返回文件的基本名稱(不包含路徑)。
  • Size方法:返回文件的大小。
  • Mode方法:返回文件的權限和模式位信息。
  • ModTime方法:返回文件最后一次修改時間。
  • IsDir方法:判斷文件是否是一個目錄。
  • Sys方法:返回底層數據源,通常是操作系統特定的文件信息(可能返回nil)。

獲取文件屬性信息示例如下:

package mainimport ("fmt""os"
)func main() {name := `D:\github\Golang-topics\src\go_code\FileOperation\FileOperation\NormalOperation\data.txt`// 1、打開文件file, err := os.OpenFile(name, os.O_RDONLY, 0666)if err != nil {if os.IsNotExist(err) {fmt.Println("warning: file not exists...")} else {fmt.Printf("open file error, err = %v\n", err)}return}// 2、延遲關閉文件defer file.Close()// 3、獲取文件屬性信息fi, err := file.Stat()if err != nil {fmt.Printf("get file info error, err = %v\n", err)return}fmt.Printf("file name = %v\n", fi.Name())       // file name = data.txtfmt.Printf("file size = %v\n", fi.Size())       // file size = 240fmt.Printf("file mode = %v\n", fi.Mode())       // file mode = -rw-rw-rw-fmt.Printf("file modTime = %v\n", fi.ModTime()) // file modTime = 2024-05-09 17:27:33.1530703 +0800 CSTfmt.Printf("file isDir = %v\n", fi.IsDir())     // file isDir = falsefmt.Printf("file sys = %v\n", fi.Sys())         // file sys = &{32 {1262805282 31105508} {690243707 31105523} {521554895 31105523} 0 240}
}

說明一下:

  • os包中的IsNotExist函數返回一個bool值,表示傳入的錯誤值是否表示文件或目錄不存在。
  • os包中也提供了單獨的Stat函數用于獲取文件的屬性信息,調用時傳入文件名稱(包括路徑)即可。

寫文件

在os包中,使用File結構體的Write方法將指定內容寫入到文件中,該方法的原型如下:

func (f *File) Write(b []byte) (n int, err error)

參數說明:

  • b:表示要寫入文件的數據。

返回值說明:

  • n:表示成功寫入文件的字節數。
  • err:如果寫入過程中出錯,將返回非nil的錯誤值。

寫文件示例如下:

package mainimport ("fmt""os""strconv"
)func main() {name := `D:\github\Golang-topics\src\go_code\FileOperation\FileOperation\NormalOperation\data.txt`// 1、打開文件file, err := os.OpenFile(name, os.O_WRONLY|os.O_CREATE, 0666)if err != nil {fmt.Printf("open file error, err = %v\n", err)return}// 2、延遲關閉文件defer file.Close()// 3、寫文件var str stringfor i := 0; i < 10; i++ {str += "Hello File(os package)" + strconv.Itoa(i) + "\n"}count, err := file.Write([]byte(str))if err != nil {fmt.Printf("write file error, err = %v\n", err)return}fmt.Printf("write %d bytes data to data.txt\n", count) // write 240 bytes data to data.txt
}

運行程序后可以看到數據被成功寫入文件。如下:

在這里插入圖片描述

讀文件

在os包中,使用File結構體的Read方法讀取文件中的內容,該方法的原型如下:

func (f *File) Read(b []byte) (n int, err error)

參數說明:

  • b:輸出型參數,用于存儲從文件中讀取到的數據。

返回值說明:

  • n:表示成功讀取到的字節數。
  • err:如果讀取過程中出錯,將返回非nil的錯誤值。

讀文件示例如下:

package mainimport ("fmt""os"
)func main() {name := `D:\github\Golang-topics\src\go_code\FileOperation\FileOperation\NormalOperation\data.txt`// 1、打開文件file, err := os.OpenFile(name, os.O_RDONLY, 0666)if err != nil {fmt.Printf("open file error, err = %v\n", err)return}// 2、延遲關閉文件defer file.Close()// 3、獲取文件大小fileInfo, err := file.Stat()if err != nil {fmt.Printf("get file info error, err = %v\n", err)return}fileSize := fileInfo.Size()// 4、讀文件buffer := make([]byte, fileSize)count, err := file.Read(buffer)if err != nil {fmt.Printf("read file error, err = %v\n", err)return}fmt.Printf("file size = %d, read count = %d\n", fileSize, count)fmt.Printf("file content:\n%s\n", string(buffer))
}

運行程序后可以看到文件中的數據被成功讀取出來。如下:

在這里插入圖片描述

其他函數和方法

在os包中,常用的打開文件獲取File對象的函數如下:

函數名功能
OpenFile打開文件,可以指明打開文件的方式和新創建文件的權限
Open以只讀模式打開文件
Create以0666權限創建并打開文件,如果文件已存在會將其截斷

在os包中,常用的File結構體提供的文件操作方法如下:

方法名功能
Name獲取文件名稱(包括路徑)
Stat獲取文件屬性信息
Fd獲取文件對應的文件描述符
Read從當前位置開始讀取文件數據
ReadAt從指定位置開始讀取文件數據
Write從當前位置開始向文件寫入數據
WriteString從當前位置開始向文件寫入一個字符串
WriteAt從指定位置開始向文件寫入數據
Seek設置下一次文件的讀寫位置
Close關閉文件

帶緩沖的文件操作方式(bufio包)

bufio包介紹

  • bufio包中的Reader和Writer類型提供了帶緩沖的讀寫功能,可以搭配os包一起使用來實現文件的帶緩沖讀寫。

Reader結構體的定義如下:

type Reader struct {buf          []byterd           io.Reader // reader provided by the clientr, w         int       // buf read and write positionserr          errorlastByte     int // last byte read for UnreadByte; -1 means invalidlastRuneSize int // size of last rune read for UnreadRune; -1 means invalid
}

Reader結構體各字段說明:

  • buf:內部緩沖區,用于臨時存儲從底層io.Reader讀取到的數據。
  • rd:創建Reader對象時提供的io.Reader對象,用于讀取數據。
  • r:緩沖區中的讀取位置,表示下一個要讀取的字節位置。
  • w:緩沖區中的寫入位置,表示下一個要寫入的字節位置。
  • err:存儲讀取數據過程中發生的錯誤。
  • lastByte:上一次讀取的字節,用于UnreadByte方法,-1表示無效。
  • lastRuneSize:上一次讀取的Unicode字符大小,用于UnreadRune方法,-1表示無效。

Reader結構體常用的方法如下:

方法名功能
Read從緩沖區中讀取數據到指定的字節切片中
ReadString從緩沖區中讀取數據到字符串中,直到遇到指定的分隔符
ReadLine從緩沖區讀取一行數據,返回的字節切片包含行尾的換行符

Writer結構體的定義如下:

type Writer struct {err errorbuf []byten   intwr  io.Writer
}

Writer結構體各字段說明:

  • err:存儲寫入數據過程中發生的錯誤。
  • buf:內部緩沖區,用于臨時存儲需要寫入到底層io.Reader的數據。
  • n:緩沖區中的有效數據長度,表示待寫入的字節數。
  • wr:創建Writer對象時提供的io.Writer對象,用于寫入數據。

Writer結構體常用的方法如下:

方法名功能
Write將字節切片中的數據寫入緩沖區
WriteString將字符串中的數據寫入緩沖區
Flush將緩沖區中的數據刷新到底層的io.Writer

說明一下:

  • Reader結構體中的lastByte字段,用于支持UnreadByte方法,該方法用于將最后讀取的字節放回緩沖區。lastRuneSize字段用于支持UnreadRune方法,該方法用于將最后讀取的Unicode字符放回緩沖區。
  • Writer結構體中不需要記錄下一次緩沖區的讀取和寫入位置,因為Writer緩沖區的寫入操作是順序進行的,不需要回退或隨機訪問緩沖區中的數據,而只有當緩沖區滿或調用Flush方法時才會讀取緩沖區中的數據,將其刷新到底層的io.Writer中,每次刷新都會讀取整個緩沖區中的數據。

寫文件

要使用bufio包對文件進行寫入操作,首先需要創建出Writer對象,bufio包中提供了兩個用于創建Writer對象的函數,它們的函數原型如下:

func NewWriter(w io.Writer) *Writer
func NewWriterSize(w io.Writer, size int) *Writer

參數說明:

  • w:創建Writer對象時提供的io.Writer對象,用于寫入數據。
  • size:表示創建的Writer對象的緩沖區大小,以字節為單位。

返回值說明:

  • 返回所創建的Writer對象的指針,該對象具有指定大小的緩沖區,如果使用NewWriter函數創建Writer對象,那么緩沖區大小默認為4096字節。

使用NewWriter或NewWriterSize函數創建Writer對象時,都需要提供一個io.Writer類型的對象。io.Writer本質是io包中的一個接口類型,其定義如下:

type Writer interface {Write(p []byte) (n int, err error)
}

io.Writer接口中只定義了一個Write方法,因此所有實現了該Write方法的類型都可以傳遞給io.Writer接口。而os包中的File結構體提供的Write方法,恰好與io.Writer接口中的Write方法簽名一致,因此File對象可以傳遞給io.Writer接口。File結構體提供的Write方法如下:

func (f *File) Write(b []byte) (n int, err error)

當bufio.Writer刷新底層緩沖區時,會回調File對象的Write方法,將緩沖區中的數據寫入到文件中,完成文件的寫入操作。案例如下:

package mainimport ("bufio""fmt""os""strconv"
)func main() {name := `D:\github\Golang-topics\src\go_code\FileOperation\FileOperation\BufferedOperation\data.txt`// 1、打開文件file, err := os.OpenFile(name, os.O_WRONLY|os.O_CREATE, 0666)if err != nil {fmt.Printf("open file error, err = %v\n", err)return}// 2、延遲關閉文件defer file.Close()// 3、寫文件var str stringfor i := 0; i < 10; i++ {str += "Hello File(bufio package)" + strconv.Itoa(i) + "\n"}writer := bufio.NewWriter(file) // 創建Writercount, err := writer.Write([]byte(str))if err != nil {fmt.Printf("write file error, err = %v\n", err)return}writer.Flush() // 刷新緩沖區fmt.Printf("write %d bytes data to data.txt\n", count) // write 270 bytes data to data.txt
}

運行程序后可以看到數據被成功寫入文件。如下:

在這里插入圖片描述

注意: 只有當Writer緩沖區滿或調用Flush方法時,才會將緩沖區中的數據刷新到底層的io.Writer中,因此在數據寫入Writer后需要Flush方法刷新緩沖區中的數據。

讀文件

要使用bufio包對文件進行讀取操作,首先需要創建出Reader對象,bufio包中提供了兩個用于創建Reader對象的函數,它們的函數原型如下:

func NewReader(rd io.Reader) *Reader
func NewReaderSize(rd io.Reader, size int) *Reader

參數說明:

  • rd:創建Reader對象時提供的io.Reader對象,用于讀取數據。
  • size:表示創建的Reader對象的緩沖區大小,以字節為單位。

返回值說明:

  • 返回所創建的Reader對象的指針,該對象具有指定大小的緩沖區,如果使用NewReader函數創建Reader對象,那么緩沖區大小默認為4096字節。

使用NewReader或NewReaderSize函數創建Reader對象時,都需要提供一個io.Reader類型的對象。io.Reader本質是io包中的一個接口類型,其定義如下:

type Reader interface {Read(p []byte) (n int, err error)
}

io.Reader接口中只定義了一個Read方法,因此所有實現了該Read方法的類型都可以傳遞給io.Reader接口。而os包中的File結構體提供的Read方法,恰好與io.Reader接口中的Read方法簽名一致,因此File對象可以傳遞給io.Reader接口。File結構體提供的Read方法如下:

func (f *File) Read(b []byte) (n int, err error)

當bufio.Reader讀取文件時,會回調File對象的Read方法,將文件中的數據讀取到緩沖區中,完成文件的讀取操作。案例如下:

package mainimport ("bufio""fmt""os"
)func main() {name := `D:\github\Golang-topics\src\go_code\FileOperation\FileOperation\BufferedOperation\data.txt`// 1、打開文件file, err := os.OpenFile(name, os.O_RDONLY, 0666)if err != nil {fmt.Printf("open file error, err = %v\n", err)return}// 2、延遲關閉文件defer file.Close()// 3、獲取文件大小fileInfo, err := file.Stat()if err != nil {fmt.Printf("get file info error, err = %v\n", err)return}fileSize := fileInfo.Size()// 4、讀文件reader := bufio.NewReader(file) // 創建Readerbuffer := make([]byte, fileSize)count, err := reader.Read(buffer)if err != nil {fmt.Printf("read file error, err = %v\n", err)return}fmt.Printf("file size = %d, read count = %d\n", fileSize, count)fmt.Printf("file content:\n%s\n", string(buffer))
}

運行程序后可以看到文件中的數據被成功讀取出來。如下:

在這里插入圖片描述

文件拷貝操作(io包)

io包介紹

在io包中,使用Copy函數能夠將數據從一個io.Reader拷貝到一個io.Writer中,該函數的函數原型如下:

func Copy(dst Writer, src Reader) (written int64, err error)

參數說明:

  • dst:表示將拷貝到的數據寫入到該io.Writer中。
  • src:表示從該io.Reader中拷貝數據。

返回值說明:

  • written:返回成功拷貝的字節數。
  • err:如果拷貝過程中出錯,將返回非nil的錯誤值。

拷貝文件

前面已經介紹過,io.Reader和io.Writer本質都是io包中的接口類型,os包中的File結構體對這兩個接口進行了實現,因此在使用io.Copy函數拷貝文件時,只需傳入src文件和dst文件的File對象即可。案例如下:

package mainimport ("fmt""io""os"
)func CopyFile(dstName string, srcName string) (err error) {// 1、以讀方式打開源文件srcFile, err := os.OpenFile(srcName, os.O_RDONLY, 0666)if err != nil {fmt.Printf("open src file error, err = %v\n", err)return}defer srcFile.Close()// 2、以寫方式打開目標文件dstFile, err := os.OpenFile(dstName, os.O_WRONLY|os.O_CREATE, 0666)if err != nil {fmt.Printf("open dst file error, err = %v\n", err)return}defer dstFile.Close()// 3、進行文件拷貝count, err := io.Copy(dstFile, srcFile)if err != nil {fmt.Printf("copy file error, err = %v\n", err)return}fmt.Printf("copy file success, copy size = %d\n", count) // copy file success, copy size = 250return
}func main() {srcName := `D:\github\Golang-topics\src\go_code\FileOperation\FileOperation\CopyOperation\src.txt`dstName := `D:\github\Golang-topics\src\go_code\FileOperation\FileOperation\CopyOperation\dst.txt`err := CopyFile(dstName, srcName)if err != nil {fmt.Printf("copy file error, err = %v\n", err)}
}

運行程序后可以看到成功完成了文件的拷貝操作。如下:

在這里插入圖片描述

命令行參數

基本介紹

基本介紹

  • 命令行參數是在運行程序時通過命令行傳遞給程序的參數,在Go中可以使用os包的Args變量來訪問命令行參數。
  • os.Args是一個字符串切片,其中第一個元素是程序本身的名稱,隨后的元素依次是傳遞給程序的命令行參數。

使用案例如下:

package mainimport ("fmt""os"
)func main() {fmt.Printf("os.Args type = %T\n", os.Args) // os.Args type = []stringfor index, value := range os.Args {fmt.Printf("args[%d] = %v\n", index, value)}
}

運行上述程序時指明命令行參數,可以看到命令行參數被逐一輸出。如下:

在這里插入圖片描述

解析命令行參數(flag包)

flag包介紹

  • 通過os包的Args變量雖然可以訪問命令行參數,但對參數的解析不是特別方便,比如各個參數的含義定義后要求嚴格的輸入順序。
  • flag包是Go標準庫中的一個包,通過flag包可以輕松定義和解析命令行參數,并且參數的輸入順序可以隨意。

flag包中常用的函數如下:

函數名功能
StringVar用于定義一個string類型的命令行參數
IntVar用于定義一個int類型的命令行參數
BoolVar用于定義一個bool類型的命令行參數
Parse用于解析命令行參數,將命令行參數的值賦給相應的變量

其中StringVar、IntVar和BoolVar函數都有四個參數,沒有返回值。各個參數的含義如下:

  • 第一個參數:指向對應類型變量的指針,用于存儲命令行參數的值。
  • 第二個參數:命令行參數的名稱。
  • 第三個參數:命令行參數的默認值,用戶未輸入該命令行參數時采用。
  • 第四個參數:命令行參數的描述信息。

解析命令行參數

例如在運行mysql命令連接MySQL服務器時,需要通過命令行參數指明用戶名、密碼、服務端IP地址和端口號等。借助flag包可以按如下方式實現:

package mainimport ("flag""fmt"
)func main() {var user, psw, ip stringvar port intflag.StringVar(&user, "u", "root", "用戶名")flag.StringVar(&psw, "p", "000000", "密碼")flag.StringVar(&ip, "h", "localhost", "IP地址")flag.IntVar(&port, "P", 3306, "端口號")flag.Parse() // 解析命令行參數fmt.Printf("user = %v\n", user)fmt.Printf("psw = %v\n", psw)fmt.Printf("ip = %v\n", ip)fmt.Printf("port = %v\n", port)
}

在運行程序時,需要通過-命令行參數名稱 命令行參數的形式,依次指明各個命令行參數,如果輸入的命令行參數名稱未定義,則會輸出一個簡單的使用手冊。如下:

在這里插入圖片描述

只有按照正確的格式指明命令行參數后程序才能正常運行,但各個命令行參數的指明順序可以隨意。對于未指明的命令行參數,將采用定義命令行參數時給定的默認值。如下:

在這里插入圖片描述

注意: 在命令行參數定義完畢后,需要調用Parse函數解析命令行參數,這樣才能將命令行參數的值賦給相應的變量。

JSON

基本介紹

基本介紹

  • JSON(JavaScript Object Notation)是一種輕量級的數據交換格式,常用于在網絡上傳輸數據,它最初是基于JavaScript語言的一個子集,但目前已經成為一種獨立于編程語言的數據格式。
  • 不同的系統和平臺通過JSON可以方便地交換和共享數據,無論其使用的是哪種編程語言,這使得JSON成為一種常用的數據交換格式,在Web開發、API設計和數據存儲中得到廣泛應用。
  • JSON序列化指的是將數據轉換為JSON格式的過程,JSON反序列化指的是將JSON格式的數據轉換為原始數據的過程。

JSON使用人類可讀的文本來表示結構化數據,采用鍵值對的方式存儲數據,其由以下幾種數據類型組成:

  • 對象:由一組無序的鍵值對組成,使用大括號{}表示。鍵是字符串,值可以是字符串、數字、布爾值、對象、數組或空值。
  • 數組:由一組有序的值組成,使用中括號[]表示。值可以是字符串、數字、布爾值、對象、數組或空值。
  • 字符串:由雙引號包圍的Unicode字符序列。
  • 數字:整數或浮點數。
  • 布爾值:true或false。
  • 空值:null。

例如下面是一個簡單的JSON字符串:

{"name": "Alice","age": 12,"gender": "女","scores": [105,128,115]
}

JSON序列化

JSON序列化

在Go中,使用encoding/json包中的Marshal函數能夠對數據進行JSON序列化,該函數的函數原型如下:

func Marshal(v interface{}) ([]byte, error)

參數說明:

  • v:需要進行JSON序列化的任意類型的數據。

返回值說明:

  • 第一個返回值:表示JSON序列化成功后得到的JSON字符串。
  • 第二個返回值:如果序列化過程中出錯,將返回非nil的錯誤值。

使用案例如下:

package mainimport ("encoding/json""fmt"
)type Student struct {Name   string         `json:"name"`Age    int            `json:"age"`Gender string         `json:"gender"`Scores map[string]int `json:"scores"`
}func main() {var stu = Student{Name:   "Alice",Age:    12,Gender: "女",Scores: map[string]int{"語文": 105,"數學": 128,"英語": 115,},}data, err := json.Marshal(stu)if err != nil {fmt.Printf("json serialize error, err = %v\n", err)return}fmt.Printf("json str = %s\n", string(data))
}

運行程序后可以看到序列化后的JSON字符串。如下:

在這里插入圖片描述

說明一下: 通過結構體字段的Tag標簽,可以指定結構體各個字段在JSON序列化時的名稱,如果沒有指定則默認使用字段名。

JSON反序列化

JSON反序列化

在Go中,使用encoding/json包中的Unmarshal函數能夠將JSON字符串反序列化為原始數據,該函數的函數原型如下:

func Unmarshal(data []byte, v interface{}) error

參數說明:

  • data:需要進行反序列化的JSON字符串。
  • v:指向目標結構體或數據的指針,用于保存反序列化后的結果。

返回值說明:

  • 反序列化成功返回nil,否則返回非nil的錯誤值。

使用案例如下:

package mainimport ("encoding/json""fmt"
)type Student struct {Name   string `json:"name"`Age    int    `json:"age"`Gender string `json:"gender"`Scores []int  `json:"scores"`
}func main() {var str = `{"name":"Alice","age":12,"gender":"女","scores":[105,128,115]}`var stu Studenterr := json.Unmarshal([]byte(str), &stu)if err != nil {fmt.Printf("json unserialize error, err = %v\n", err)return}fmt.Printf("stu = %v\n", stu)
}

運行程序后可以看到反序列化后的Student對象。如下:

在這里插入圖片描述

注意: 要確保反序列化的數據類型與序列化前的數據類型一致,否則會反序列化失敗。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/15868.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/15868.shtml
英文地址,請注明出處:http://en.pswp.cn/web/15868.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【MySQL精通之路】MySQL的使用(3)-連接到服務器的配置

目錄 1.連接建立的命令選項 1.1.--default-auth 1.2.--hosthost_name, -h host_name 1.3.--password[pass_val], -p[pass_val] 1.4.--password1[pass_val] 1.5.--password2[pass_val] 1.6.--password3[pass_val] 1.7.--pipe, -W 1.8.--plugin-dirdir_name 1.9.--port…

【YOLOv10訓練】:報錯 AttributeError: ‘str‘ object has no attribute ‘view‘ 解決方法

YOLOv10訓練報錯 YOLOv10是在YOLOv8基礎上修改的&#xff0c;即&#xff1a;訓練方法和過程是相同的。 但按照v8訓練程序train.py&#xff0c;如下所示&#xff0c;直接訓練&#xff1a; from ultralytics import YOLO# Load a model model YOLO("ultralytics/cfg/mod…

真拿AI賺到錢的人,不在朋友圈里

1 最近有張兩大AI巨頭對比的梗圖給我看樂了&#xff0c;玩兒AI的還在做產品&#xff0c;玩兒焦慮的已經在數錢了。 這也是在做AI&#xff0c;只不過是唉聲嘆氣的ai。 要我說&#xff0c;現在缺的根本不是AI&#xff0c;而是【有用的AI】。 恩格斯老師說過一句話&#xff1a…

科林Linux6_網絡

#include<sys/socket.h> #include<arpa/inet.h> //大小端轉換 #include<netdb.h> //DNS一、Socket套接字 為了開發網絡應用&#xff0c;系統提供一套API函數接口&#xff0c;用于網絡應用開發&#xff0c;這些接口稱為套接字函數 struct sockaddr_in…

數據庫管理-第194期 網絡加速RDMA初探(20240526)

數據庫管理194期 2024-05-26 數據庫管理-第194期 網絡加速RDMA初探&#xff08;20240526&#xff09;1 概念2 發展3 使用總結 數據庫管理-第194期 網絡加速RDMA初探&#xff08;20240526&#xff09; 作者&#xff1a;胖頭魚的魚缸&#xff08;尹海文&#xff09; Oracle ACE A…

英文 海量的學習句子比單獨的記單詞效果要好,格句致知。

英文 海量的學習句子比單獨的記單詞效果要好 句子有上下文、場景和時態等&#xff0c;能形成劇情&#xff0c;變得生動有趣。 如果一句沒聽懂&#xff0c;還繼續聽就是浪費時間了。要一句一句地深究&#xff0c;不然就要讀好幾遍&#xff0c;還得背誦。要深入理解&#xff0c…

不同的二叉搜索樹(II)題解

toc &#x1f91a;我的博客 歡迎光臨我的博客&#xff1a;https://blog.csdn.net/qq_52434217?typeblog &#x1f95b;前言 動態規劃是常見的算法思路&#xff0c;動態規劃在計算過程中保存了部分計算結果到內存中&#xff0c;以便于在進行下一次計算時可以直接從內存中獲…

Ubuntu部署Dolphinscheduler單機版并配置PG數據庫

1、下載并解壓Dolphinscheduler DolphinScheduler | 下載 (apache.org) 下載完成后得tar.gz包 下載穩定版 下載穩定版 下載穩定版 tar -zxvf apache-dolphinscheduler-3.1.9-alpha-bin.tar.gz mv apache-dolphinscheduler-3.1.9-alpha-bin dolphinscheduler-bin cd dolph…

【Text2SQL】Spider 數據集

論文&#xff1a;Spider: A Large-Scale Human-Labeled Dataset for Complex and Cross-Domain Semantic Parsing and Text-to-SQL Task ????? EMNLP 2018, arXiv:1809.08887 Dataset: spider GitHub: github.com/taoyds/spider 一、論文速讀 本文提出了 Text2SQL 方向的…

1.4 Mac 電腦 Clion 安裝教程

目錄 1 安裝 2 激活 3 漢化 1 安裝 去 https://www.jetbrains.com/clion/download/other.html 下載: 也可以直接到鏈接進行下載:https

嵌入式全棧開發學習筆記---C語言筆試復習大全23

目錄 聯合體 聯合體的定義 聯合體的長度 如果來判斷設備的字節序&#xff1f; 如何把大端數據轉換成小端數據&#xff1f; 枚舉 枚舉的定義 上一篇復習了結構體&#xff0c;這一節復習聯合體和枚舉。 說明&#xff1a;我們學過單片機的一般都是有C語言基礎的了&#xff…

docker鏡像容器搭建nominatim地理編碼服務

1、下載地圖pbf文件: https://planet.openstreetmap.org/ 2、nominatim官網 https://nominatim.org/release-docs/latest/admin/Installation/ 3、地圖文件打包&#xff1a; docker run -it --shm-size20g \ -e PBF_PATH/nominatim/data/china-latest.osm.pbf \ -e REPLIC…

C語言PTA練習題:三角形類別,輸入三角形三條邊,求面積,四則計算器,猴子吃桃

7-1 三角形類別 輸入三個整數&#xff0c;以這三個數為邊長&#xff0c;判斷是否構成三角形&#xff1b;若不能輸出"no"&#xff0c;若構成三角形&#xff0c;進一步判斷它們構的是&#xff1a;銳角三角形或直角三角形或鈍角三角形.分別輸出"ruijiao",&qu…

GitLens或者Git Graph在vscode中對比文件歷史變化,并將歷史變化同步到當前文件中

有時候我們上周改的代碼&#xff0c;現在想反悔把它恢復過來&#xff0c;怎么辦&#xff1f;&#xff1f;&#xff1f;很好&#xff0c;你有這個需求&#xff0c;說明你找對人了&#xff0c;那就是我們需要在vscode中安裝這個插件&#xff1a;GitLens或者Git Graph&#xff0c;…

門禁-jenkins的構建狀態同步到gitlab提交流水線

API接口文檔 https://docs.gitlab.cn/jh/api/commits.html 配置pipline流水線 生成http請求代碼&#xff1a; 使用HttpRequest插件生成 - sharelibs內容 //這是share libs里的 package devopsdef httpReq(reqType, reqUrl, reqBody, accessToken){def gitServer "…

有一個3x4的矩陣,要求用函數編寫程序求出其中值最大的那個元素,以及其所在的行號和列號

常量和變量可以用作函數實參&#xff0c;同樣數組元素也可以作函數實參&#xff0c;其用法與變量相同。數組名也可以作實參和形參&#xff0c;傳遞的是數組的起始地址。 用數組元素作函數實參&#xff1a; 由于實參可以是表達式&#xff0c;而數組元素可以是表達式的組…

Oracle 12C開機自啟動

Oracle 12C設置開機自啟動 1、本文內容 背景說明檢查Oracle當前環境修改配置文件/etc/oratab添加數據庫啟動腳本dbstart 2、背景說明 最近因上線新的兩套系統&#xff0c;增加4套測試環境&#xff0c;由于昨晚機房電路故障&#xff0c;部分物理服務器需要關鍵&#xff0c;電…

2000 年至 2015 年中國(即水稻、小麥和玉米1km 網格)三種主要作物年收獲面積的時空變化

摘要 可靠、連續的主要作物收獲面積信息對于研究地表動態和制定影響農業生產、土地利用和可持續發展的政策至關重要。然而&#xff0c;中國目前還沒有高分辨率的空間明確和時間連續的作物收獲面積信息。全國范圍內主要農作物收獲面積的時空格局也鮮有研究。在本研究中&#xf…

2024年【熔化焊接與熱切割】考試內容及熔化焊接與熱切割考試報名

題庫來源&#xff1a;安全生產模擬考試一點通公眾號小程序 熔化焊接與熱切割考試內容考前必練&#xff01;安全生產模擬考試一點通每個月更新熔化焊接與熱切割考試報名題目及答案&#xff01;多做幾遍&#xff0c;其實通過熔化焊接與熱切割復審模擬考試很簡單。 1、【單選題】…