Golang六個常用接口的使用總結(jié)
在上一篇文章中,我們講解了接口,對于很多初學(xué)者來說,接口很抽象,我們有時候不知道如何定義自己的接口,基于此,在這篇文章中,我們來學(xué)習(xí)幾個Go標準庫的接口,看看Go標準庫是如何定義接口,以加深對Go語言接口的理解。
fmt.Stringer
在開發(fā)過程,我們經(jīng)常會調(diào)用fmt包下的打印函數(shù)(如println或printf)將調(diào)試信息輸出到控制臺:
fmt.Println("test")
fmt.Printf("%d\n",10)這些打印函數(shù)會自動決定如何在控制臺輸出這些信息,對于自定義類型,如果我們想自定義其在控制臺的輸出,要怎么做呢?
fmt包的Stringer用于定義類型的格式化輸出,該接口的定義如下:
type Stringer interface {
String() string
}對于實現(xiàn)了Stringer接口的類型,打印函數(shù)會自動調(diào)用該類型的String()方法,將該方法的返回值輸出到控制臺,比如我們自定義一個Reason類型,用于表示季節(jié):
package main
type Reason uint
const (
SPRING Reason = iota + 1
SUMMER
AUTUMN
WINTER
)
func main() {
fmt.Println(SPRING) //輸出:1
fmt.Println(SUMMER) //輸出:2
fmt.Println(AUTUMN) //輸出:3
fmt.Println(WINTER) //輸出:4
}實現(xiàn)Stringer接口后,就可以將Reason類以中文的格式打印出來了:
func (r Reason) String() string {
return ReasonText[r] //自定義輸出:將數(shù)值轉(zhuǎn)化為文本
}
var ReasonText = map[Reason]string{
SPRING: "春天",
SUMMER: "夏天",
AUTUMN: "秋天",
WINTER: "冬天",
}
func main() {
fmt.Println(SPRING) //輸出:春天
fmt.Println(SUMMER) //輸出:夏天
fmt.Println(AUTUMN) //輸出:秋天
fmt.Println(WINTER) //輸出:冬天
}sort.Interface
除了格式化輸出信息外,排序功能也是開發(fā)中經(jīng)常用到的,Go標準庫的sort包的Sort()就是常用的排序函數(shù),該函數(shù)定義如下:
func Sort(data Interface) {
n := data.Len()
quickSort(data, 0, n, maxDepth(n))
}可以看到,Sort函數(shù)接收一個Inferface類型的參數(shù),Interface類型是一個接口,其定義如下:
type Interface interface {
Len() int
Less(i, j int) bool
Swap(i, j int)
}Interface類型的Len方法用于返回長度,Less方法用于元素比較大小,Swap方法實現(xiàn)元素位置交換,任何擁有這個方法的類型,都可以傳遞給sort.Sort進行排序。
下面是一個實現(xiàn)sort.Interface接口,并調(diào)用sort.Sort函數(shù)的示例:
package main
import (
"fmt"
"sort"
)
type Student struct {
ID int
Name string
Score int
}
type Students []Student
func (s Students) Len() int {
return len(s)
}
func (s Students) Less(i, j int) bool {
return s[i].Score > s[j].Score
}
func (s Students) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func main() {
students := []Student{
{ID: 1, Name: "A", Score: 95},
{ID: 2, Name: "B", Score: 100},
{ID: 3, Name: "C", Score: 90},
{ID: 4, Name: "D", Score: 80},
}
sort.Sort(Students(students))
fmt.Println(students)
}io.Reader和io.Writer
網(wǎng)絡(luò)數(shù)據(jù)的讀取與發(fā)送、文件的讀取與寫入,本質(zhì)都是寫入或取出一段字節(jié)數(shù)據(jù)(即字節(jié)數(shù)組),Go標準庫對字節(jié)的讀取與寫入抽象為io包的Reader和Writer接口:
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}在Go標準庫內(nèi)有很多實現(xiàn)了io.Reader和io.Writer接口,比如os.File或者Response.Boy:
package main
import (
"io"
"net/http"
"os"
)
func main() {
url := ""
response, err := http.Get(url)
if err != nil {
panic(err)
}
//os.Stdout是os.File類型
io.Copy(os.Stdout, response.Body)
}上面我們調(diào)用io.Copy方法將請求到的數(shù)據(jù)輸出到控制臺,io.Copy函數(shù)定義如下:
func Copy(dst Writer, src Reader) (written int64, err error) {
return copyBuffer(dst, src, nil)
}可以看到這個方法接收的參數(shù)就是Writer和Reader接口,我們也可以自定義類型來實現(xiàn)Writer或者Reader接口:
package main
import (
"fmt"
"io"
"net/http"
)
type Data string
func (d *Data) Write(p []byte) (n int, err error) {
n = len(p)
*d = Data(string(p))
return n, nil
}
func main() {
url := ""
response, err := http.Get(url)
if err != nil {
panic(err)
}
var d Data
io.Copy(&d, response.Body)
fmt.Println(d)
}error
Go語言的函數(shù)支持多個返回值,一般推薦把error類型作為函數(shù)最后一個返回值,用于告訴調(diào)用者函數(shù)調(diào)用是否發(fā)生錯誤,error類型實際上就是一個接口:
type error interface {
Error() string
}可以看到error只定義了一個方法,該方法返回一個字符串的錯誤信息,我們可以使用errors包的方法創(chuàng)建并返回一個error類型:
var err error = errors.New("Not Found")也可以在實現(xiàn)error接口的基礎(chǔ),包含更多的錯誤信息,方便調(diào)用者判斷錯誤類型:
package main
import (
"fmt"
"os"
)
type FileNotFound struct {
Message string
FileName string
err error
}
func (f FileNotFound) Error() string {
return f.Message
}
func GetLogFile(fileName string) (*os.File, error) {
f, err := os.Open(fileName)
if err != nil {
return nil, &FileNotFound{FileName: fileName, err: err, Message: "Not found"}
}
return f, nil
}
func main() {
var err error
f, err = GetLogFile("1.txt")
if e, ok := err.(FileNotFound); ok {
fmt.Println(e.Message)
}
}http.Handler
http包的Handler接口定義如下,該接口定義了處理HTTP請求應(yīng)該實現(xiàn)的方法。
type Handler interface {
ServeHTTP(w ResponseWriter, r *Request)
}在Go語言中,只需要簡單的幾行代碼便可以啟動一個Web服務(wù)器:
package main
import "net/http"
func main() {
http.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("User Info"))
})
http.ListenAndServe(":8080", nil)
}http.HandleFunc()會將我們自己的匿名函數(shù)封裝為HandlerFunc函數(shù),HandlerFunc函數(shù)的定義如下,可以看到這個函數(shù)實現(xiàn)了Handler接口:
type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}關(guān)于Go的Web開發(fā)部分,我們后面在其他文章再詳細講解!
小結(jié)
幾個Go接口講解下來,你會發(fā)現(xiàn),其實Go標準庫定義的接口簡單且通用,一個接口就只描述一種行為,這就是Go語言的編程哲學(xué)是一個接口只做一件事,只完成一個功能,將多個功能堆砌在同一個接口內(nèi)是不可取的。
另外也不要在開發(fā)某個具體類型前預(yù)定義好接口,而是當多個類型有共同行為但卻有不同實現(xiàn)的時候,才用接口加以概括和描述。
到此這篇關(guān)于Golang六個常用接口的使用總結(jié)的文章就介紹到這了,更多相關(guān)Golang接口內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
golang實現(xiàn)sql結(jié)果集以json格式輸出的方法
這篇文章主要介紹了golang實現(xiàn)sql結(jié)果集以json格式輸出的方法,涉及Go語言針對sql結(jié)果集的遍歷、轉(zhuǎn)換及json格式相關(guān)操作技巧,需要的朋友可以參考下2017-03-03
Go語言crypto包創(chuàng)建自己的密碼加密工具實現(xiàn)示例
Go語言借助它的簡單性和強大的標準庫,實現(xiàn)一個自己的密碼加密工具,本文將會結(jié)合代碼示例深入探討如何使用Go語言的crypto包來實現(xiàn)自己的加密工具2023-11-11
Go語言內(nèi)建函數(shù)cap的實現(xiàn)示例
cap 是一個常用的內(nèi)建函數(shù),它用于獲取某些數(shù)據(jù)結(jié)構(gòu)的容量,本文主要介紹了Go語言內(nèi)建函數(shù)cap的實現(xiàn)示例,具有一定的參考價值,感興趣的可以了解一下2024-08-08
Golang多線程下載器實現(xiàn)高效快速地下載大文件
Golang多線程下載器是一種高效、快速地下載大文件的方法。Golang語言天生支持并發(fā)和多線程,可以輕松實現(xiàn)多線程下載器的開發(fā)。通過使用Golang的協(xié)程和通道,可以將下載任務(wù)分配到多個線程中并行處理,提高了下載的效率和速度2023-05-05
詳解go語言 make(chan int, 1) 和 make (chan int) 的區(qū)別
這篇文章主要介紹了go語言 make(chan int, 1) 和 make (chan int) 的區(qū)別,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2020-01-01

