From 668d296f4f072b5fd73e7337305231ce6863b53a Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Thu, 5 Oct 2017 22:48:56 +0800 Subject: [PATCH 1/9] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20feed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/http/controller/feed.go | 89 +++++++++++++++++++++++++++++++++++ src/http/controller/routes.go | 2 + src/vendor/manifest | 6 +++ 3 files changed, 97 insertions(+) create mode 100644 src/http/controller/feed.go diff --git a/src/http/controller/feed.go b/src/http/controller/feed.go new file mode 100644 index 00000000..dadcfd60 --- /dev/null +++ b/src/http/controller/feed.go @@ -0,0 +1,89 @@ +// Copyright 2016 The StudyGolang Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// http://studygolang.com +// Author: polaris polaris@studygolang.com + +package controller + +import ( + "logic" + "model" + "net/http" + "time" + + . "http" + + "github.com/gorilla/feeds" + "github.com/labstack/echo" +) + +type FeedController struct{} + +// 注册路由 +func (self FeedController) RegisterRoute(g *echo.Group) { + g.Get("/feed", self.List) +} + +func (self FeedController) List(ctx echo.Context) error { + link := "http://" + logic.WebsiteSetting.Domain + isHttps := CheckIsHttps(ctx) + if isHttps { + link = "https://" + logic.WebsiteSetting.Domain + } + + now := time.Now() + + feed := &feeds.Feed{ + Title: logic.WebsiteSetting.Name, + Link: &feeds.Link{Href: link}, + Description: logic.WebsiteSetting.Slogan, + Author: &feeds.Author{Name: "polaris", Email: "polaris@studygolang.com"}, + Created: now, + Updated: now, + } + + siteFeeds := logic.DefaultFeed.FindRecent(ctx, 50) + + feed.Items = make([]*feeds.Item, len(siteFeeds)) + + for i, siteFeed := range siteFeeds { + strObjtype := "" + switch siteFeed.Objtype { + case model.TypeTopic: + strObjtype = "主题" + case model.TypeResource: + strObjtype = "资源" + case model.TypeArticle: + strObjtype = "文章" + case model.TypeProject: + strObjtype = "开源项目" + case model.TypeBook: + strObjtype = "图书" + case model.TypeWiki: + strObjtype = "Wiki" + } + feed.Items[i] = &feeds.Item{ + Title: siteFeed.Title, + Link: &feeds.Link{Href: link + siteFeed.Uri}, + Description: "这是" + strObjtype, + Created: time.Time(siteFeed.CreatedAt), + Updated: time.Time(siteFeed.UpdatedAt), + } + } + + atom, err := feed.ToAtom() + if err != nil { + return err + } + + return self.responseXML(ctx, atom) +} + +func (FeedController) responseXML(ctx echo.Context, data string) (err error) { + response := ctx.Response() + response.Header().Set(echo.HeaderContentType, echo.MIMEApplicationXMLCharsetUTF8) + response.WriteHeader(http.StatusOK) + _, err = response.Write([]byte(data)) + return +} diff --git a/src/http/controller/routes.go b/src/http/controller/routes.go index f7fa2825..5bb4a234 100644 --- a/src/http/controller/routes.go +++ b/src/http/controller/routes.go @@ -37,6 +37,8 @@ func RegisterRoutes(g *echo.Group) { new(DownloadController).RegisterRoute(g) new(LinkController).RegisterRoute(g) + new(FeedController).RegisterRoute(g) + new(WechatController).RegisterRoute(g) new(InstallController).RegisterRoute(g) diff --git a/src/vendor/manifest b/src/vendor/manifest index 70813443..e1b35a11 100644 --- a/src/vendor/manifest +++ b/src/vendor/manifest @@ -145,6 +145,12 @@ "revision": "1ea25387ff6f684839d82767c1733ff4d4d15d0a", "branch": "master" }, + { + "importpath": "github.com/gorilla/feeds", + "repository": "https://github.com/gorilla/feeds", + "revision": "b78e02c3f88b84269be5c20c2b98127bbea1fcba", + "branch": "master" + }, { "importpath": "github.com/gorilla/schema", "repository": "https://github.com/gorilla/schema", From ab7a524b774d0f58287be09469ec6db7bc654a89 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Thu, 5 Oct 2017 22:56:46 +0800 Subject: [PATCH 2/9] feed xml --- src/http/controller/feed.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/http/controller/feed.go b/src/http/controller/feed.go index dadcfd60..1e0e92e3 100644 --- a/src/http/controller/feed.go +++ b/src/http/controller/feed.go @@ -22,7 +22,7 @@ type FeedController struct{} // 注册路由 func (self FeedController) RegisterRoute(g *echo.Group) { - g.Get("/feed", self.List) + g.Get("/feedx.xml", self.List) } func (self FeedController) List(ctx echo.Context) error { From 683299f5c63d190bd082fce12123caeb854161b1 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Thu, 5 Oct 2017 22:58:10 +0800 Subject: [PATCH 3/9] feed xml --- src/http/controller/feed.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/http/controller/feed.go b/src/http/controller/feed.go index 1e0e92e3..ee237bda 100644 --- a/src/http/controller/feed.go +++ b/src/http/controller/feed.go @@ -22,7 +22,7 @@ type FeedController struct{} // 注册路由 func (self FeedController) RegisterRoute(g *echo.Group) { - g.Get("/feedx.xml", self.List) + g.Get("/feed.xml", self.List) } func (self FeedController) List(ctx echo.Context) error { From 792f5e0a65a7abf2cec2ee9c1acf84f3e56b28b1 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Fri, 6 Oct 2017 20:08:05 +0800 Subject: [PATCH 4/9] =?UTF-8?q?atom=20feed=20=E8=AE=A2=E9=98=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/http/controller/feed.go | 56 ++++++++++++++++++++++--------------- src/logic/searcher.go | 33 ++++++++++++++++++++++ template/atom.html | 30 ++++++++++++++++++++ 3 files changed, 97 insertions(+), 22 deletions(-) create mode 100644 template/atom.html diff --git a/src/http/controller/feed.go b/src/http/controller/feed.go index ee237bda..76cb5ada 100644 --- a/src/http/controller/feed.go +++ b/src/http/controller/feed.go @@ -7,6 +7,7 @@ package controller import ( + "fmt" "logic" "model" "net/http" @@ -22,14 +23,20 @@ type FeedController struct{} // 注册路由 func (self FeedController) RegisterRoute(g *echo.Group) { + g.Get("/feed.html", self.Atom) g.Get("/feed.xml", self.List) } +func (self FeedController) Atom(ctx echo.Context) error { + return Render(ctx, "atom.html", map[string]interface{}{}) +} + func (self FeedController) List(ctx echo.Context) error { - link := "http://" + logic.WebsiteSetting.Domain - isHttps := CheckIsHttps(ctx) - if isHttps { - link = "https://" + logic.WebsiteSetting.Domain + link := logic.WebsiteSetting.Domain + if logic.WebsiteSetting.OnlyHttps { + link = "https://" + link + } else { + link = "http://" + link } now := time.Now() @@ -43,32 +50,37 @@ func (self FeedController) List(ctx echo.Context) error { Updated: now, } - siteFeeds := logic.DefaultFeed.FindRecent(ctx, 50) + respBody, err := logic.DefaultSearcher.FindAtomFeeds(50) + if err != nil { + return err + } + + feed.Items = make([]*feeds.Item, len(respBody.Docs)) - feed.Items = make([]*feeds.Item, len(siteFeeds)) + for i, doc := range respBody.Docs { + url := "" - for i, siteFeed := range siteFeeds { - strObjtype := "" - switch siteFeed.Objtype { + switch doc.Objtype { case model.TypeTopic: - strObjtype = "主题" - case model.TypeResource: - strObjtype = "资源" + url = fmt.Sprintf("%s/topics/%d", link, doc.Objid) case model.TypeArticle: - strObjtype = "文章" + url = fmt.Sprintf("%s/articles/%d", link, doc.Objid) + case model.TypeResource: + url = fmt.Sprintf("%s/resources/%d", link, doc.Objid) case model.TypeProject: - strObjtype = "开源项目" - case model.TypeBook: - strObjtype = "图书" + url = fmt.Sprintf("%s/p/%d", link, doc.Objid) case model.TypeWiki: - strObjtype = "Wiki" + url = fmt.Sprintf("%s/wiki/%d", link, doc.Objid) + case model.TypeBook: + url = fmt.Sprintf("%s/book/%d", link, doc.Objid) } feed.Items[i] = &feeds.Item{ - Title: siteFeed.Title, - Link: &feeds.Link{Href: link + siteFeed.Uri}, - Description: "这是" + strObjtype, - Created: time.Time(siteFeed.CreatedAt), - Updated: time.Time(siteFeed.UpdatedAt), + Title: doc.Title, + Link: &feeds.Link{Href: url}, + Author: &feeds.Author{Name: doc.Author}, + Description: doc.Content, + Created: time.Time(doc.SortTime), + Updated: time.Time(doc.UpdatedAt), } } diff --git a/src/logic/searcher.go b/src/logic/searcher.go index d1c3096f..46ee05b4 100644 --- a/src/logic/searcher.go +++ b/src/logic/searcher.go @@ -417,6 +417,39 @@ func (this *SearcherLogic) SearchByField(field, value string, start, rows int, s return searchResponse.RespBody, nil } +func (this *SearcherLogic) FindAtomFeeds(rows int) (*model.ResponseBody, error) { + selectUrl := this.engineUrl + "/select?" + + var values = url.Values{ + "q": []string{"*:*"}, + "sort": []string{"sort_time desc"}, + "wt": []string{"json"}, + "start": []string{"0"}, + "rows": []string{strconv.Itoa(rows)}, + } + + resp, err := http.Get(selectUrl + values.Encode()) + if err != nil { + logger.Errorln("search error:", err) + return &model.ResponseBody{}, err + } + + defer resp.Body.Close() + + var searchResponse model.SearchResponse + err = json.NewDecoder(resp.Body).Decode(&searchResponse) + if err != nil { + logger.Errorln("parse response error:", err) + return &model.ResponseBody{}, err + } + + if searchResponse.RespBody == nil { + searchResponse.RespBody = &model.ResponseBody{} + } + + return searchResponse.RespBody, nil +} + func (this *SearcherLogic) FillNodeAndUser(ctx context.Context, respBody *model.ResponseBody) (map[int]*model.User, map[int]*model.TopicNode) { if respBody.NumFound == 0 { return nil, nil diff --git a/template/atom.html b/template/atom.html new file mode 100644 index 00000000..c2348831 --- /dev/null +++ b/template/atom.html @@ -0,0 +1,30 @@ +{{define "title"}}Feed订阅 {{end}} +{{define "content"}} +
+
+
+
+ +
+ +
+
+

欢迎订阅下面的Feed,您可以及时跟踪我的更新:

+

+ + +
+
+
+
+
+ + {{include "common/my_info.html" .}} +
+
+{{end}} \ No newline at end of file From 9082878777e9a45a1dd25163792a2107d30b6c9f Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Fri, 6 Oct 2017 21:25:02 +0800 Subject: [PATCH 5/9] =?UTF-8?q?=E5=A2=9E=E9=87=8F=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/db.sql | 2 +- src/logic/searcher.go | 287 +++++++++++++++++++++++------------------- src/server/server.go | 4 + 3 files changed, 164 insertions(+), 129 deletions(-) diff --git a/config/db.sql b/config/db.sql index 24a85197..7c8bb3ef 100644 --- a/config/db.sql +++ b/config/db.sql @@ -321,7 +321,7 @@ CREATE TABLE IF NOT EXISTS `articles` ( KEY (`top`), KEY (`author_txt`), KEY (`domain`), - KEY (`ctime`) + KEY (`mtime`) )ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT '网络文章聚合表'; CREATE TABLE IF NOT EXISTS `crawl_rule` ( diff --git a/src/logic/searcher.go b/src/logic/searcher.go index 46ee05b4..a7ca788c 100644 --- a/src/logic/searcher.go +++ b/src/logic/searcher.go @@ -13,6 +13,7 @@ import ( "net/http" "net/url" "strconv" + "time" "util" . "db" @@ -51,44 +52,51 @@ func (self SearcherLogic) IndexingArticle(isAll bool) { err error ) - if isAll { - id := 0 - for { - articleList = make([]*model.Article, 0) + id := 0 + for { + articleList = make([]*model.Article, 0) + if isAll { err = MasterDB.Where("id>?", id).Limit(self.maxRows).OrderBy("id ASC").Find(&articleList) - if err != nil { - logger.Errorln("IndexingArticle error:", err) - break - } + } else { + timeAgo := time.Now().Add(-5 * time.Minute).Format("2006-01-02 15:04:05") + err = MasterDB.Where("mtime>?", timeAgo).Find(&articleList) + } + if err != nil { + logger.Errorln("IndexingArticle error:", err) + break + } - if len(articleList) == 0 { - break - } + if len(articleList) == 0 { + break + } - for _, article := range articleList { - logger.Infoln("deal article_id:", article.Id) + for _, article := range articleList { + logger.Infoln("deal article_id:", article.Id) - if id < article.Id { - id = article.Id - } + if id < article.Id { + id = article.Id + } - if article.Tags == "" { - // 自动生成 - article.Tags = model.AutoTag(article.Title, article.Txt, 4) - if article.Tags != "" { - MasterDB.Id(article.Id).Cols("tags").Update(article) - } + if article.Tags == "" { + // 自动生成 + article.Tags = model.AutoTag(article.Title, article.Txt, 4) + if article.Tags != "" { + MasterDB.Id(article.Id).Cols("tags").Update(article) } + } - document := model.NewDocument(article, nil) - if article.Status != model.ArticleStatusOffline { - solrClient.PushAdd(model.NewDefaultArgsAddCommand(document)) - } else { - solrClient.PushDel(model.NewDelCommand(document)) - } + document := model.NewDocument(article, nil) + if article.Status != model.ArticleStatusOffline { + solrClient.PushAdd(model.NewDefaultArgsAddCommand(document)) + } else { + solrClient.PushDel(model.NewDelCommand(document)) } + } - solrClient.Post() + solrClient.Post() + + if !isAll { + break } } } @@ -104,54 +112,61 @@ func (self SearcherLogic) IndexingTopic(isAll bool) { err error ) - if isAll { - id := 0 - for { - topicList = make([]*model.Topic, 0) - topicExList = make(map[int]*model.TopicUpEx) + id := 0 + for { + topicList = make([]*model.Topic, 0) + topicExList = make(map[int]*model.TopicUpEx) + if isAll { err = MasterDB.Where("tid>?", id).OrderBy("tid ASC").Limit(self.maxRows).Find(&topicList) - if err != nil { - logger.Errorln("IndexingTopic error:", err) - break - } + } else { + timeAgo := time.Now().Add(-5 * time.Minute).Format("2006-01-02 15:04:05") + err = MasterDB.Where("mtime>?", timeAgo).Find(&topicList) + } + if err != nil { + logger.Errorln("IndexingTopic error:", err) + break + } - if len(topicList) == 0 { - break - } + if len(topicList) == 0 { + break + } - tids := util.Models2Intslice(topicList, "Tid") + tids := util.Models2Intslice(topicList, "Tid") - err = MasterDB.In("tid", tids).Find(&topicExList) - if err != nil { - logger.Errorln("IndexingTopic error:", err) - break - } + err = MasterDB.In("tid", tids).Find(&topicExList) + if err != nil { + logger.Errorln("IndexingTopic error:", err) + break + } - for _, topic := range topicList { - logger.Infoln("deal topic_id:", topic.Tid) + for _, topic := range topicList { + logger.Infoln("deal topic_id:", topic.Tid) - if id < topic.Tid { - id = topic.Tid - } + if id < topic.Tid { + id = topic.Tid + } - if topic.Tags == "" { - // 自动生成 - topic.Tags = model.AutoTag(topic.Title, topic.Content, 4) - if topic.Tags != "" { - MasterDB.Id(topic.Tid).Cols("tags").Update(topic) - } + if topic.Tags == "" { + // 自动生成 + topic.Tags = model.AutoTag(topic.Title, topic.Content, 4) + if topic.Tags != "" { + MasterDB.Id(topic.Tid).Cols("tags").Update(topic) } + } - topicEx := topicExList[topic.Tid] + topicEx := topicExList[topic.Tid] - document := model.NewDocument(topic, topicEx) - addCommand := model.NewDefaultArgsAddCommand(document) + document := model.NewDocument(topic, topicEx) + addCommand := model.NewDefaultArgsAddCommand(document) - solrClient.PushAdd(addCommand) - } + solrClient.PushAdd(addCommand) + } - solrClient.Post() + solrClient.Post() + + if !isAll { + break } } } @@ -166,54 +181,61 @@ func (self SearcherLogic) IndexingResource(isAll bool) { err error ) - if isAll { - id := 0 - for { - resourceList = make([]*model.Resource, 0) - resourceExList = make(map[int]*model.ResourceEx) + id := 0 + for { + resourceList = make([]*model.Resource, 0) + resourceExList = make(map[int]*model.ResourceEx) + if isAll { err = MasterDB.Where("id>?", id).OrderBy("id ASC").Limit(self.maxRows).Find(&resourceList) - if err != nil { - logger.Errorln("IndexingResource error:", err) - break - } + } else { + timeAgo := time.Now().Add(-5 * time.Minute).Format("2006-01-02 15:04:05") + err = MasterDB.Where("mtime>?", timeAgo).Find(&resourceList) + } + if err != nil { + logger.Errorln("IndexingResource error:", err) + break + } - if len(resourceList) == 0 { - break - } + if len(resourceList) == 0 { + break + } - ids := util.Models2Intslice(resourceList, "Id") + ids := util.Models2Intslice(resourceList, "Id") - err = MasterDB.In("id", ids).Find(&resourceExList) - if err != nil { - logger.Errorln("IndexingResource error:", err) - break - } + err = MasterDB.In("id", ids).Find(&resourceExList) + if err != nil { + logger.Errorln("IndexingResource error:", err) + break + } - for _, resource := range resourceList { - logger.Infoln("deal resource_id:", resource.Id) + for _, resource := range resourceList { + logger.Infoln("deal resource_id:", resource.Id) - if id < resource.Id { - id = resource.Id - } + if id < resource.Id { + id = resource.Id + } - if resource.Tags == "" { - // 自动生成 - resource.Tags = model.AutoTag(resource.Title+resource.CatName, resource.Content, 4) - if resource.Tags != "" { - MasterDB.Id(resource.Id).Cols("tags").Update(resource) - } + if resource.Tags == "" { + // 自动生成 + resource.Tags = model.AutoTag(resource.Title+resource.CatName, resource.Content, 4) + if resource.Tags != "" { + MasterDB.Id(resource.Id).Cols("tags").Update(resource) } + } - resourceEx := resourceExList[resource.Id] + resourceEx := resourceExList[resource.Id] - document := model.NewDocument(resource, resourceEx) - addCommand := model.NewDefaultArgsAddCommand(document) + document := model.NewDocument(resource, resourceEx) + addCommand := model.NewDefaultArgsAddCommand(document) - solrClient.PushAdd(addCommand) - } + solrClient.PushAdd(addCommand) + } + + solrClient.Post() - solrClient.Post() + if !isAll { + break } } } @@ -227,46 +249,55 @@ func (self SearcherLogic) IndexingOpenProject(isAll bool) { err error ) - if isAll { - id := 0 - for { - projectList = make([]*model.OpenProject, 0) + id := 0 + for { + projectList = make([]*model.OpenProject, 0) + + if isAll { err = MasterDB.Where("id>?", id).OrderBy("id ASC").Limit(self.maxRows).Find(&projectList) - if err != nil { - logger.Errorln("IndexingArticle error:", err) - break - } + } else { + timeAgo := time.Now().Add(-5 * time.Minute).Format("2006-01-02 15:04:05") + err = MasterDB.Where("mtime>?", timeAgo).Find(&projectList) + } + if err != nil { + logger.Errorln("IndexingArticle error:", err) + break + } - if len(projectList) == 0 { - break - } + if len(projectList) == 0 { + break + } - for _, project := range projectList { - logger.Infoln("deal project_id:", project.Id) + for _, project := range projectList { + logger.Infoln("deal project_id:", project.Id) - if id < project.Id { - id = project.Id - } + if id < project.Id { + id = project.Id + } - if project.Tags == "" { - // 自动生成 - project.Tags = model.AutoTag(project.Name+project.Category, project.Desc, 4) - if project.Tags != "" { - MasterDB.Id(project.Id).Cols("tags").Update(project) - } + if project.Tags == "" { + // 自动生成 + project.Tags = model.AutoTag(project.Name+project.Category, project.Desc, 4) + if project.Tags != "" { + MasterDB.Id(project.Id).Cols("tags").Update(project) } + } - document := model.NewDocument(project, nil) - if project.Status != model.ProjectStatusOffline { - solrClient.PushAdd(model.NewDefaultArgsAddCommand(document)) - } else { - solrClient.PushDel(model.NewDelCommand(document)) - } + document := model.NewDocument(project, nil) + if project.Status != model.ProjectStatusOffline { + solrClient.PushAdd(model.NewDefaultArgsAddCommand(document)) + } else { + solrClient.PushDel(model.NewDelCommand(document)) } + } - solrClient.Post() + solrClient.Post() + + if !isAll { + break } } + } const searchContentLen = 350 diff --git a/src/server/server.go b/src/server/server.go index 8582912d..ab1832d5 100644 --- a/src/server/server.go +++ b/src/server/server.go @@ -36,6 +36,10 @@ func IndexingServer() { c := cron.New() // 构建 solr 需要的索引数据 + // 1 分钟一次增量 + c.AddFunc("@every 1m", func() { + indexing(false) + }) // 一天一次全量 c.AddFunc("@daily", func() { indexing(true) From 61b4f471902b716d4f3f9fb64bec64c27ed3ecb8 Mon Sep 17 00:00:00 2001 From: xuxinhua Date: Mon, 9 Oct 2017 13:59:40 +0800 Subject: [PATCH 6/9] =?UTF-8?q?=E6=9C=80=E6=96=B0go=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- install.sh | 1 - src/http/controller/feed.go | 4 +- template/download/go.html | 818 ++++++++++++++++++++++++++++-------- 3 files changed, 649 insertions(+), 174 deletions(-) diff --git a/install.sh b/install.sh index 3a9f6262..b4774733 100755 --- a/install.sh +++ b/install.sh @@ -24,7 +24,6 @@ go install server/indexer go install server/crawler export GOPATH="$OLDGOPATH" -export PATH="$OLDPATH" echo 'finished' diff --git a/src/http/controller/feed.go b/src/http/controller/feed.go index 76cb5ada..0c5413c3 100644 --- a/src/http/controller/feed.go +++ b/src/http/controller/feed.go @@ -34,9 +34,9 @@ func (self FeedController) Atom(ctx echo.Context) error { func (self FeedController) List(ctx echo.Context) error { link := logic.WebsiteSetting.Domain if logic.WebsiteSetting.OnlyHttps { - link = "https://" + link + link = "https://" + link + "/" } else { - link = "http://" + link + link = "http://" + link + "/" } now := time.Now() diff --git a/template/download/go.html b/template/download/go.html index 1644f259..4809567d 100644 --- a/template/download/go.html +++ b/template/download/go.html @@ -31,37 +31,37 @@

Go 安装包下载

- +
Microsoft Windows
Windows XP SP2 or later, Intel 64-bit 处理器
- go1.9.windows-amd64.msi + go1.9.1.windows-amd64.msi (90MB)
- +
Apple macOS
macOS 10.8 or later, Intel 64-bit 处理器
- go1.9.darwin-amd64.pkg + go1.9.1.darwin-amd64.pkg (97MB)
- +
Linux
Linux 2.6.23 or later, Intel 64-bit 处理器
- go1.9.linux-amd64.tar.gz - (98MB) + go1.9.1.linux-amd64.tar.gz + (99MB)
- +
源码
- go1.9.src.tar.gz + go1.9.1.src.tar.gz (16MB)
@@ -69,171 +69,330 @@

稳定版本

- -
- -
-

go1.9 ▾

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
+ +
+

go1.9.1 ▾

+ + +
文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
go1.9.src.tar.gzSource16MBa4ab229028ed167ba1986825751463605264e44868362ca8e7accc8be057e993
go1.9.darwin-amd64.tar.gzArchivemacOSx86-6498MBc2df361ec6c26fcf20d5569496182cb20728caa4d351bc430b2f0f1212cca3e0
go1.9.darwin-amd64.pkgInstallermacOSx86-6497MB2197814c83fc04569f5fabf030f835c95e48562afc48cbc96264665dc552f7a1
go1.9.linux-386.tar.gzArchiveLinuxx8686MB7cccff99dacf59162cd67f5b11070d667691397fd421b0a9ad287da019debc4f
go1.9.linux-amd64.tar.gzArchiveLinuxx86-6498MBd70eadefce8e160638a9a6db97f7192d8463069ab33138893ad3bf31b0650a79
go1.9.linux-armv6l.tar.gzArchiveLinuxARMv685MBf52ca5933f7a8de2daf7a3172b0406353622c6a39e67dd08bbbeb84c6496f487
go1.9.windows-386.zipArchiveWindowsx8692MBecfe6f5be56acedc56cd9ff735f239a12a7c94f40b0ea9753bbfd17396f5e4b9
go1.9.windows-386.msiInstallerWindowsx8679MB1db7a0bcdfcc78f816cf4f83df9edfc31ee9a3b3bc40ee751e193d92ee44cf31
go1.9.windows-amd64.zipArchiveWindowsx86-64104MB874b144b994643cff1d3f5875369d65c01c216bb23b8edddf608facc43966c8b
go1.9.windows-amd64.msiInstallerWindowsx86-6490MB955c91d353b9a3ca2e41a1d980850141996501b3118ab09d049a2bb267103c2b
Other Ports
go1.9.freebsd-386.tar.gzArchiveFreeBSDx8686MB9e415e340eaea526170b0fd59aa55939ff4f76c126193002971e8c6799e2ed3a
go1.9.freebsd-amd64.tar.gzArchiveFreeBSDx86-6498MBba54efb2223fb4145604dcaf8605d519467f418ab02c081d3cd0632b6b43b6e7
go1.9.linux-arm64.tar.gzArchiveLinuxARMv884MB0958dcf454f7f26d7acc1a4ddc34220d499df845bc2051c14ff8efdf1e3c29a6
go1.9.linux-ppc64le.tar.gzArchiveLinuxppc64le84MB10b66dae326b32a56d4c295747df564616ec46ed0079553e88e39d4f1b2ae985
go1.9.linux-s390x.tar.gzArchiveLinuxs390x83MBe06231e4918528e2eba1d3cff9bc4310b777971e5d8985f9772c6018694a3af8
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
go1.9.1.src.tar.gzSource16MBa84afc9dc7d64fe0fa84d4d735e2ece23831a22117b50dafc75c1484f1cb550e
go1.9.1.darwin-amd64.tar.gzArchivemacOSx86-6498MB59bc6deee2969dddc4490b684b15f63058177f5c7e27134c060288b7d76faab0
go1.9.1.darwin-amd64.pkgInstallermacOSx86-6497MB80c37f023206b261d0f4481d830959237c033b7a9f69c8ef5f48e96c3e8d8cff
go1.9.1.linux-386.tar.gzArchiveLinuxx8688MB2cea1ce9325cb40839601b566bc02b11c92b2942c21110b1b254c7e72e5581e7
go1.9.1.linux-amd64.tar.gzArchiveLinuxx86-6499MB07d81c6b6b4c2dcf1b5ef7c27aaebd3691cdb40548500941f92b221147c5d9c7
go1.9.1.linux-armv6l.tar.gzArchiveLinuxARMv685MB65a0495a50c7c240a6487b1170939586332f6c8f3526abdbb9140935b3cff14c
go1.9.1.windows-386.zipArchiveWindowsx8692MBea9c79c9e6214c9a78a107ef5a7bff775a281bffe8c2d50afa66d2d33998078a
go1.9.1.windows-386.msiInstallerWindowsx8679MBc939b62e32ba3048321546a111c732868b66fe1b58ae9c12b723a02a6a02b27c
go1.9.1.windows-amd64.zipArchiveWindowsx86-64105MB8dc72a3881388e4e560c2e45f6be59860b623ad418e7da94e80fee012221cc81
go1.9.1.windows-amd64.msiInstallerWindowsx86-6490MB49627bd99f26384452471256d6eca7860399fbcac8684a108713c321f8043486
Other Ports
go1.9.1.freebsd-386.tar.gzArchiveFreeBSDx8686MB0da7ad96606a8ceea85652eb20816077769d51de9219d85b9b224a3390070c50
go1.9.1.freebsd-amd64.tar.gzArchiveFreeBSDx86-6498MBc4eeacbb94821c5f252897a4d49c78293eaa97b29652d789dce9e79bc6aa6163
go1.9.1.linux-arm64.tar.gzArchiveLinuxARMv884MBd31ecae36efea5197af271ccce86ccc2baf10d2e04f20d0fb75556ecf0614dad
go1.9.1.linux-ppc64le.tar.gzArchiveLinuxppc64le84MBde57b6439ce9d4dd8b528599317a35fa1e09d6aa93b0a80e3945018658d963b8
go1.9.1.linux-s390x.tar.gzArchiveLinuxs390x83MB9adf03574549db82a72e0d721ef2178ec5e51d1ce4f309b271a2bca4dcf206f6
+ +
+
- +
+ +
+

go1.8.4 ▾

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
go1.8.4.src.tar.gzSource15MBabf1b2e5ae2a4845f3d2eac00c7382ff209e2c132dc35b7ce753da9b4f52e59f
go1.8.4.darwin-amd64.tar.gzArchivemacOSx86-6493MBcf803053aec24425d7be986af6dff0051bb48527bcdfa5b9ffeb4d40701ab54e
go1.8.4.darwin-amd64.pkgInstallermacOSx86-6492MBf541593cc9f141dbc7ba13ef1512882bddda8ed32bd0a188a2494d7d453d015b
go1.8.4.linux-386.tar.gzArchiveLinuxx8683MB00354388d5f7d21b69c62361e73250d2633124e8599386f704f6dd676a2f82ac
go1.8.4.linux-amd64.tar.gzArchiveLinuxx86-6494MB0ef737a0aff9742af0f63ac13c97ce36f0bbc8b67385169e41e395f34170944f
go1.8.4.linux-armv6l.tar.gzArchiveLinuxARMv682MB76329898bb9f2be0f86b07f05a6336818cb12f3a416ab3061aa0d5f2ea5c6ff0
go1.8.4.windows-386.zipArchiveWindowsx8687MBc0f949174332e5b9d4f025c84338bbec1c94b436f249c20aade04a024537f0be
go1.8.4.windows-386.msiInstallerWindowsx8675MB79d22dfd70eac5231cbb6ff22cdb699bc520fc6f1e6cbbaf000c687b9fd81cbf
go1.8.4.windows-amd64.zipArchiveWindowsx86-64100MB2ddfea037fd5e2eeb0cb854c095f6e44aaec27e8bbf76dca9a11a88e3a49bbf7
go1.8.4.windows-amd64.msiInstallerWindowsx86-6486MB4db2ce3c570854dd047aff38a978d9271049e901bfd4703c6be72eae3d91296c
Other Ports
go1.8.4.freebsd-386.tar.gzArchiveFreeBSDx8681MB4764920bc94cc9723e7a9a65ae7764922e0ab6148e1cf206bbf37062997fdf4c
go1.8.4.freebsd-amd64.tar.gzArchiveFreeBSDx86-6493MB21dd9899b91f4aaeeb85c7bb7db6cd4b44be089b2a7397ea8f9f2e3397a0b5c6
go1.8.4.linux-ppc64le.tar.gzArchiveLinuxppc64le80MB0f043568d65fd8121af6b35a39f4f20d292a03372b6531e80b743ee0689eb717
go1.8.4.linux-s390x.tar.gzArchiveLinuxs390x79MBaa998b7ac8882c549f7017d2e9722a3102cb9e6b92010baf5153a6dcf98205b1
+ +
+
- - @@ -415,6 +574,323 @@

历史版本归档▹

历史版本归档▾

+
+ +
+

go1.9 ▾

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
go1.9.src.tar.gzSource16MBa4ab229028ed167ba1986825751463605264e44868362ca8e7accc8be057e993
go1.9.darwin-amd64.tar.gzArchivemacOSx86-6498MBc2df361ec6c26fcf20d5569496182cb20728caa4d351bc430b2f0f1212cca3e0
go1.9.darwin-amd64.pkgInstallermacOSx86-6497MB2197814c83fc04569f5fabf030f835c95e48562afc48cbc96264665dc552f7a1
go1.9.linux-386.tar.gzArchiveLinuxx8686MB7cccff99dacf59162cd67f5b11070d667691397fd421b0a9ad287da019debc4f
go1.9.linux-amd64.tar.gzArchiveLinuxx86-6498MBd70eadefce8e160638a9a6db97f7192d8463069ab33138893ad3bf31b0650a79
go1.9.linux-armv6l.tar.gzArchiveLinuxARMv685MBf52ca5933f7a8de2daf7a3172b0406353622c6a39e67dd08bbbeb84c6496f487
go1.9.windows-386.zipArchiveWindowsx8692MBecfe6f5be56acedc56cd9ff735f239a12a7c94f40b0ea9753bbfd17396f5e4b9
go1.9.windows-386.msiInstallerWindowsx8679MB1db7a0bcdfcc78f816cf4f83df9edfc31ee9a3b3bc40ee751e193d92ee44cf31
go1.9.windows-amd64.zipArchiveWindowsx86-64104MB874b144b994643cff1d3f5875369d65c01c216bb23b8edddf608facc43966c8b
go1.9.windows-amd64.msiInstallerWindowsx86-6490MB955c91d353b9a3ca2e41a1d980850141996501b3118ab09d049a2bb267103c2b
Other Ports
go1.9.freebsd-386.tar.gzArchiveFreeBSDx8686MB9e415e340eaea526170b0fd59aa55939ff4f76c126193002971e8c6799e2ed3a
go1.9.freebsd-amd64.tar.gzArchiveFreeBSDx86-6498MBba54efb2223fb4145604dcaf8605d519467f418ab02c081d3cd0632b6b43b6e7
go1.9.linux-arm64.tar.gzArchiveLinuxARMv884MB0958dcf454f7f26d7acc1a4ddc34220d499df845bc2051c14ff8efdf1e3c29a6
go1.9.linux-ppc64le.tar.gzArchiveLinuxppc64le84MB10b66dae326b32a56d4c295747df564616ec46ed0079553e88e39d4f1b2ae985
go1.9.linux-s390x.tar.gzArchiveLinuxs390x83MBe06231e4918528e2eba1d3cff9bc4310b777971e5d8985f9772c6018694a3af8
+ +
+
+ +
+ +
+

go1.8.3 ▾

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
文件名类型操作系统(OS)架构(Arch)大小SHA256 Checksum
go1.8.3.src.tar.gzSource15MB5f5dea2447e7dcfdc50fa6b94c512e58bfba5673c039259fd843f68829d99fa6
go1.8.3.darwin-amd64.tar.gzArchivemacOSx86-6486MBf20b92bc7d4ab22aa18270087c478a74463bd64a893a94264434a38a4b167c05
go1.8.3.darwin-amd64.pkgInstallermacOSx86-6485MBf81c8911dc76cd2b4ddd3d7ea845fe7ed83abd493b382fff216e1a8f637b5e7f
go1.8.3.freebsd-386.tar.gzArchiveFreeBSDx8674MBd301cc7c2b8b0ccb384ac564531beee8220727fd27ca190b92031a2e3e230224
go1.8.3.freebsd-amd64.tar.gzArchiveFreeBSDx86-6486MB1bf5f076d48609012fe01b95e2a58e71e56719a04d576fe3484a216ad4b9c495
go1.8.3.linux-386.tar.gzArchiveLinuxx8674MBff4895eb68fb1daaec41c540602e8bb4c1e8bb2f0e7017367171913fc9995ed2
go1.8.3.linux-amd64.tar.gzArchiveLinuxx86-6486MB1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772
go1.8.3.linux-armv6l.tar.gzArchiveLinuxARMv674MB3c30a3e24736ca776fc6314e5092fb8584bd3a4a2c2fa7307ae779ba2735e668
go1.8.3.linux-ppc64le.tar.gzArchiveLinuxppc64le73MBe5fb00adfc7291e657f1f3d31c09e74890b5328e6f991a3f395ca72a8c4dc0b3
go1.8.3.linux-s390x.tar.gzArchiveLinuxs390x72MBe2ec3e7c293701b57ca1f32b37977ac9968f57b3df034f2cc2d531e80671e6c8
go1.8.3.windows-386.zipArchiveWindowsx8680MB9e2bfcb8110a3c56f23b91f859963269bc29fd114190fecfd0a539395272a1c7
go1.8.3.windows-386.msiInstallerWindowsx8667MBc1df97e6f9afc2db1705f0f1d04fa31804d5c9b995cca26680881baaa1543eb4
go1.8.3.windows-amd64.zipArchiveWindowsx86-6492MBde026caef4c5b4a74f359737dcb2d14c67ca45c45093755d3b0d2e0ee3aafd96
go1.8.3.windows-amd64.msiInstallerWindowsx86-6478MB35734d9331fe4ee19725213d8e98840660460fd1b90518fffc79c0f856a3586a
+ +
+