<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ## 5.11\. 接口和其他類型 ### 5.11.1\. 接口 Go中的接口提供了一類對象的抽象。我們在前面已經看到了關于接口的一些例子。 我們可以給新定義的對象實現一個String方法,這樣就可以用 Fprintf輸出該類型的值。同樣,Fprintf可以將 結果輸出到任意實現了Write方法的對象。接口一般只包含一類方法, 并且以ed后綴的方式命名,例如io.Writer接口對應Write 方法實現。 一種類型可以實現多個接口。例如,如果想支持sort包中的排序 方法,那么只需要實現sort.Interface接口的Len()、 Less()、Swap(i, j int)方法就可以了。下面的例子 實現了sort.Interface接口的同時,還定制了輸出函數。 ``` type Sequence []int // Methods required by sort.Interface. func (s Sequence) Len() int { return len(s) } func (s Sequence) Less(i, j int) bool { return s[i] < s[j] } func (s Sequence) Swap(i, j int) { s[i], s[j] = s[j], s[i] } // Method for printing - sorts the elements before printing. func (s Sequence) String() string { sort.Sort(s) str := "[" for i, elem := range s { if i > 0 { str += " " } str += fmt.Sprint(elem) } return str + "]" } ``` ### 5.11.2\. 轉換 Sequence 的 String 方法重做了 Sprint 在切片的工作。我們可以在調用 Sprint 前把 Sequence 轉為普通的 []int。 ``` func (s Sequence) String() string { sort.Sort(s) return fmt.Sprint([]int(s)) } ``` 轉換使得 s 被當作普通的切片,因此得到默認的排版。不加轉換,Sprint 會發現 Sequence 的 String 方法,進而無窮遞歸。如果忽略類型名稱,Sequence 和 []int 的類型相同, 它們之間的轉換是合法的。轉換不會得到新值,它只是暫時假裝現有值是新類型。(其它合法的轉換,如從整型到浮點型,會生成新值。) 地道的 Go 程序會轉換表達式的類型來使用一組不同的方法。例如,我們可以用現有類型 sort.IntArray 把整個例子縮減為: ``` type Sequence []int // Method for printing - sorts the elements before printing func (s Sequence) String() string { sort.IntArray(s).Sort() return fmt.Sprint([]int(s)) } ``` 現在,無需讓 Sequence 實現多個界面(排序和打印),我們使用了把數據轉換為多種類型(Sequence,sort.IntArray 和 []int)的能力,每個來完成一部分的工作。這實際上不常見但很有效。 ### 5.11.3\. Generality(泛化) 如果某類型的存在只為了實現某界面,而除此之外沒有其它導出的方法,則此類型也不需導出。只導出界面明確了只有行為有價值,而不是實現,其它的不同特性的實現可以鏡像其原來的類型。這樣也避免了為同一方法的不同實現做文檔。 此時,架構函數應返回界面而不是實現類型。例如,哈希庫的crc32.NewIEEE() 和 adler32.New() 都返回界面類型 hash.Hash32。 替換一個 Go 出現的 CRC-32 算法為 Adler-32 只需改變架構函數的調用;其余的代碼不受算法改變的影響。 同樣的方式使得 crypto/block 包的流密(streaming cipher)算法與鏈接在一起的塊密(block cipher)相區隔。比對 bu?o 包,它們包裝了界面,返回 hash.Hash,io.Reader 和 io.Writer 界面值,而不是特定的實現。 crypto/block 界面包括: ``` type Cipher interface { BlockSize() int Encrypt(src, dst []byte) Decrypt(src, dst []byte) } // NewECBDecrypter returns a reader that reads data // from r and decrypts it using c in electronic codebook (ECB) mode. func NewECBDecrypter(c Cipher, r io.Reader) io.Reader // NewCBCDecrypter returns a reader that reads data // from r and decrypts it using c in cipher block chaining (CBC) mode // with the initialization vector iv. func NewCBCDecrypter(c Cipher, iv []byte, r io.Reader) io.Reader ``` NewECBDecrypter 和 NewCBCReader 不只用于某特定的加密算法和數據源,而是任意的 Cipher 界面的實現和任意的 io.Reader。因為它們返回 io.Reader 界面值,替換 ECB 加密為 CBC 加密只是局部修改。 架構函數必須編輯,但因為周圍代碼必須只把結果作為io.Reader,它不會注意到有什么不同。 ### 5.11.4\. 接口和方法 因為幾乎任何東西都可加以方法,幾乎任何東西都可滿足某界面。一個展示的例子是 http 包定義的 Handler 界面。任何物件實現了Handler 都可服務 HTTP 請求。 ``` type Handler interface { ServeHTTP(*Conn, *Request) } ``` ResponseWriter 本身是個界面,它提供一些可訪問的方法來返回客戶的請求。這些方法包括標準的 Write 方法。因此 http.ResponseWriter 可用在 io.Writer 可以使用的地方。Request 是個結構,包含客戶請求的一個解析過的表示。 為求簡短,我們忽略 POST 并假定所有 HTTP 請求都是 GET;此簡化不會影響經手者的設置。下面一個小而全的經手者實現了網頁訪問次數的計數。 ``` // Simple counter server. type Counter struct { n int } func (ctr *Counter) ServeHTTP(c *http.Conn, req *http.Request) { ctr.n++ fmt.Fprintf(c, "counter = %d\n", ctr.n) } ``` (注意 Fprintf 怎樣打印到 http.ResponseWriter)。作為參考,這里是怎樣把服務者加在一個 URL 樹的節點上。 ``` import "http" ... ctr := new(Counter) http.Handle("/counter", ctr) ``` 可是為何把 Counter 作為結構呢?一個整數能夠了。(接受者需是指針,使增量帶回調用者)。 ``` // Simpler counter server. type Counter int func (ctr *Counter) ServeHTTP(c *http.Conn, req *http.Request) { *ctr++ fmt.Fprintf(c, "counter = %d\n", *ctr) } ``` 當某頁被訪問時怎樣通知你的程序更新某些內部狀態呢?給網頁貼個信道。 ``` // A channel that sends a notification on each visit. // (Probably want the channel to be buffered.) type Chan chan *http.Request func (ch Chan) ServeHTTP(c *http.Conn, req *http.Request) { ch <- req fmt.Fprint(c, "notification sent") } ``` 最后,讓我們在 /args 顯示啟動服務器時的參量。寫個打印參量的函數很容易: ``` func ArgServer() { for i, s := range os.Args { fmt.Println(s) } } ``` 怎樣把它變成 HTTP 服務器呢?我們可以把 ArgServer 作為某個類型的方法再忽略其值,也有更干凈的做法。既然我們可以給任意非指針和界面的類型定義方法,我們可以給函數寫個方法。http 包里有如下代碼: ``` // The HandlerFunc type is an adapter to allow the use of // ordinary functions as HTTP handlers. If f is a function // with the appropriate signature, HandlerFunc(f) is a // Handler object that calls f. type HandlerFunc func(*Conn, *Request) // ServeHTTP calls f(c, req). func (f HandlerFunc) ServeHTTP(c *Conn, req *Request) { f(c, req) } ``` HandlerFunc 是個帶 ServeHTTP 方法的類型, 所以此類的值都可以服務 HTTP 請求。我們來看看此方法的實現:接受者是個函數,f,方法調用 f 。看起來很怪,但和,比如,接受者是信道,而方法發送到 此信道,沒什么不同。 要把 ArgServer 變為 HTTP 服務器, 我們首先改成正確的簽名: ``` // Argument server. func ArgServer(c *http.Conn, req *http.Request) { for i, s := range os.Args { fmt.Fprintln(c, s) } } ``` ArgServer 現在和 HandlerFunc 有同樣的簽名,就可以轉成此類使用其方法,就像我們把 Sequence 轉為 IntArray 來使用 IntArray.Sort 一樣。設置代碼很簡短: ``` http.Handle("/args", http.HandlerFunc(ArgServer)) ``` 當有人訪問 /args 頁時,此頁的經手者有值 ArgServer 和類型HandlerFunc。HTTP 服務器啟動此類型的 ServeHTTP 方法,用ArgServer 作為接受者,反過來調用 ArgServer (通過啟動handlerFunc.ServeHTTP 的 f(w, req) 。)參量被顯示出來。 此節中我們從一個結構,整數,信道和一個函數制造出一個 HTTP 服務器,全賴于界面就是一套方法,可定義在(幾乎)任何類型上。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看