golang自动更新怎么实现

Python018

golang自动更新怎么实现,第1张

首先理解是错的,不管用户态的API(syscall)是否是同步还是异步,在kernel层面都是异步的。

其实实现原理很简单,就是利用C(嵌入汇编)语言可以直接修改寄存器(setcontext/setjmp/longjmp均是类似原理,修改程序指针eip实现跳转,栈指针实现上线文切换)来实现从func_a调进去,从func_b返回出来这种行为。对于golang来说,func_a/func_b属于不同的goroutine,从而就实现了goroutine的调度切换。

另外对于所有可能阻塞的syscall,golang对其进行了封装,底层实际是epoll方式做的,注册回调后切换到另一个runnable的goroutine。

以前使用wordpress搭建网站,插件太多,完善起来比较费时费力。现在,静态博客也很受欢迎,hugo就是GO语言开发的一个静态博客生成器。

mackbook上直接使用 brew install hugo 安装hugo,安装完成后使用 hugo version 来查看hugo的版本。

在Github目录下打开终端,或者cd到Github目录下:

hugo new site site_name

其中,si te_name为github账号名称加上 .github.io ,例如:

hugo new site gary-hertel.github.io

创建成功后会显示一些信息,诸如:

这就表示站点已经创建成功了。

然后进入到站点目录:

cd gary-hertel.github.io

使用 tree 查看目录结构如下:

接下来需要为我们的网站指定一个主题,这里我们选择 even 这个主题:

git clone https://github.com/olOwOlo/hugo-theme-even themes/even

将该主题增加到网站的配置文件中,这样才能生效:

echo 'theme = "even"' >>config.toml

测试下是否成功,运行:

hugo serve

这里是按照别的教程操作的,但是发生了报错,查看even这个主题的文档后发现有如下内容:

这里提示我们查看 themes/even/exampleSite 目录下有一个示例的 config 配置文件,我们需要将这个文件复制到站点根目录,覆盖原文件,这样才能够使站点生效。配置文件中的信息可以查看一下,然后进行相应的修改。

在站点根目录:

hugo new post/first_article.md

查看 gary-hertel.github.io/content/post 目录下新增了一个 first_article.md 的markdown文档,打开之后对其进行编辑即可,注意将 draft:true 修改为 false .

撰写文章的方法就是通常开发者常用的markdown格式。

在站点根目录下:

Hugo serve

然后就可以在浏览器中输入 http://127.0.0.1:1313/ 进行查看了,在撰写文章或者进行配置修改等等操作时,内容会自动更新。

hugo -d docs

静态页面会保存至站点根目录下的docs文件夹。

每次更新后我们都需要执行一下这条命令。

在github上新建一个公开仓库,名为github用户名加上 .github.io ,例如 gary-hertel.github.io

在仓库的settings的pages设置中,Source那里设置为:

说明如下:

使用hugo搭建个个人博客还是不错的,一开始要花些时间折腾和摸索,后续就使用起来比较方便了,也不需要购买服务器去部署,部署在github上可能国内访问较慢,可以考虑部署到gitee.

Go 由于不支持泛型而臭名昭著,但最近,泛型已接近成为现实。Go 团队实施了一个看起来比较稳定的设计草案,并且正以源到源翻译器原型的形式获得关注。本文讲述的是泛型的最新设计,以及如何自己尝试泛型。

例子

FIFO Stack

假设你要创建一个先进先出堆栈。没有泛型,你可能会这样实现:

type Stack []interface{}func (s Stack) Peek() interface{} {

 

return s[len(s)-1]

}

func (s *Stack) Pop() {

 *s = (*s)[:

len(*s)-1]

}

func (s *Stack) Push(value interface{}) {

 *s = 

append(*s, value)

}

但是,这里存在一个问题:每当你 Peek 项时,都必须使用类型断言将其从 interface{} 转换为你需要的类型。如果你的堆栈是 *MyObject 的堆栈,则意味着很多 s.Peek().(*MyObject)这样的代码。这不仅让人眼花缭乱,而且还可能引发错误。比如忘记 * 怎么办?或者如果您输入错误的类型怎么办?s.Push(MyObject{})` 可以顺利编译,而且你可能不会发现到自己的错误,直到它影响到你的整个服务为止。

通常,使用 interface{} 是相对危险的。使用更多受限制的类型总是更安全,因为可以在编译时而不是运行时发现问题。

泛型通过允许类型具有类型参数来解决此问题:

type Stack(type T) []Tfunc (s Stack(T)) Peek() T {

 

return s[len(s)-1]

}

func (s *Stack(T)) Pop() {

 *s = (*s)[:

len(*s)-1]

}

func (s *Stack(T)) Push(value T) {

 *s = 

append(*s, value)

}

这会向 Stack 添加一个类型参数,从而完全不需要 interface{}。现在,当你使用 Peek() 时,返回的值已经是原始类型,并且没有机会返回错误的值类型。这种方式更安全,更容易使用。(译注:就是看起来更丑陋,^-^)

此外,泛型代码通常更易于编译器优化,从而获得更好的性能(以二进制大小为代价)。如果我们对上面的非泛型代码和泛型代码进行基准测试,我们可以看到区别:

type MyObject struct {

    X 

int

}

var sink MyObjectfunc BenchmarkGo1(b *testing.B) {

 

for i := 0 i < b.N i++ {

  

var s Stack

  s.Push(MyObject{})

  s.Push(MyObject{})

  s.Pop()

  sink = s.Peek().(MyObject)

 }

}

func BenchmarkGo2(b *testing.B) {

 

for i := 0 i < b.N i++ {

  

var s Stack(MyObject)

  s.Push(MyObject{})

  s.Push(MyObject{})

  s.Pop()

  sink = s.Peek()

 }

}

结果:

BenchmarkGo1BenchmarkGo1-16     12837528         87.0 ns/op       48 B/op        2 allocs/opBenchmarkGo2BenchmarkGo2-16     28406479         41.9 ns/op       24 B/op        2 allocs/op

在这种情况下,我们分配更少的内存,同时泛型的速度是非泛型的两倍。

合约(Contracts)

上面的堆栈示例适用于任何类型。但是,在许多情况下,你需要编写仅适用于具有某些特征的类型的代码。例如,你可能希望堆栈要求类型实现 String() 函数