带读 |《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.

你可能感兴趣的:(go)