乐趣区

关于go:带读-Go-in-Action中文Go语言实战-三

init

init 内容

本书举荐将 map 映射(或者叫注册)之类的筹备工作放在 init 外面,Golang 会保障 init 中的函数在 main 函数调用之前执行结束。例如:

// init registers the default matcher with the program.
func init() {
    var matcher defaultMatcher
    Register("default", matcher)
}

// Register is called to register a matcher for use by the program.
func Register(feedType string, matcher Matcher) {if _, exists := matchers[feedType]; exists {log.Fatalln(feedType, "Matcher already registered")
    }

    log.Println("Register", feedType, "matcher")
    matchers[feedType] = matcher
}

如何应用 init

咱们应用下划线标识符作为别名导入包,实现了这个调用。这种办法能够让编译器在导入未被援用的包时不报错,而且依旧会定位到包内的 init 函数。代码如下:

import (
    _ "December15/sample/matchers"
    "December15/sample/search"
)

构造类型

golang 中没有类的概念,这里的构造类型的作用就相当于 java 外面的类,例如这里定义了 4 个类:

type (
    // item defines the fields associated with the item tag
    // in the rss document.
    item struct {
        XMLName     xml.Name `xml:"item"`
        PubDate     string   `xml:"pubDate"`
        Title       string   `xml:"title"`
        Description string   `xml:"description"`
        Link        string   `xml:"link"`
        GUID        string   `xml:"guid"`
        GeoRssPoint string   `xml:"georss:point"`
    }

    // image defines the fields associated with the image tag
    // in the rss document.
    image struct {
        XMLName xml.Name `xml:"image"`
        URL     string   `xml:"url"`
        Title   string   `xml:"title"`
        Link    string   `xml:"link"`
    }

    // channel defines the fields associated with the channel tag
    // in the rss document.
    channel struct {
        XMLName        xml.Name `xml:"channel"`
        Title          string   `xml:"title"`
        Description    string   `xml:"description"`
        Link           string   `xml:"link"`
        PubDate        string   `xml:"pubDate"`
        LastBuildDate  string   `xml:"lastBuildDate"`
        TTL            string   `xml:"ttl"`
        Language       string   `xml:"language"`
        ManagingEditor string   `xml:"managingEditor"`
        WebMaster      string   `xml:"webMaster"`
        Image          image    `xml:"image"`
        Item           []item   `xml:"item"`}

    // rssDocument defines the fields associated with the rss document.
    rssDocument struct {
        XMLName xml.Name `xml:"rss"`
        Channel channel  `xml:"channel"`
    }
)

空构造实现接口

本书举荐在不须要保护任何状态的时候,用空构造体来实现接口,比方:

cxtype rssMatcher struct{}

func (m rssMatcher) Search(feed *search.Feed, searchTerm string) ([]*search.Result, error) {...}

网络申请

Golang 能够十分分不便的进行网络申请,例如:

// retrieve performs a HTTP Get request for the rss feed and decodes the results.
func (m rssMatcher) retrieve(feed *search.Feed) (*rssDocument, error) {
    if feed.URI == "" {return nil, errors.New("No rss feed uri provided")
    }

    // Retrieve the rss feed document from the web.
    resp, err := http.Get(feed.URI)
    if err != nil {return nil, err}

    // Close the response once we return from the function.
    defer resp.Body.Close()

    // Check the status code for a 200 so we know we have received a
    // proper response.
    if resp.StatusCode != 200 {return nil, fmt.Errorf("HTTP Response Error %d\n", resp.StatusCode)
    }

    // Decode the rss feed document into our struct type.
    // We don't need to check for errors, the caller can do this.
    var document rssDocument
    err = xml.NewDecoder(resp.Body).Decode(&document)
    return &document, err
}

参考:Kennedy W , Ketelsen B , Martin E S . Go in action. 2016.

退出移动版