golang !_该走了! 通过示例学习Golang

golang !

我最近对区块链开源社区产生了兴趣。 我注意到的第一件事是,我遇到的大多数项目都是用Go编写的。 围棋很久以来一直是我的关注对象,因为社区对此感到非常兴奋并对此表示高度赞扬。

为什么去?

Go是一种静态类型的编译语言,例如C ++和Java。 它遵循语法和语义上“ C”的简单性,并具有一些附加功能。

例行程序

与较早的编程语言(Python,Java等)相比,Go是在2009年发布的。Go的构建考虑了并发性,并具有有效利用多处理器的能力。 Rob Pike(Go创作者)对此进行了深入讨论。 最终结果是运行并发go例程比使用Java等其他语言的线程要便宜得多。 这使我们可以无忧地同时运行数千个goroutine (甚至在单个处理器上!),并且使其成为需要扩展的问题的理想解决方案。

代码执行

Go直接在基础硬件上运行。 Go不在VM上执行,这意味着我们的代码被直接编译为二进制文件以在处理器上运行。 消除中间人VM(例如Java中的JVM)意味着perf尽可能地低,并且我们能够通过消除不必要的抽象来微调和优化代码,以最大程度地发挥作用。和性能命中。

职能是头等公民

在Go中,将函数视为其他任何数据类型。 这意味着函数可以返回函数,接受函数等。 这使我们能够利用函数式编程范例(我喜欢!),并编写更清晰,更清晰的代码。

可维护性

Go语法简洁明了。 此外,它还有一个出色的格式化程序,可以以单一方式格式化代码。 这听起来似乎很痛苦,但实际上解决了许多围绕编码约定的麻烦。Go消除了许多语言功能(IMO),这些功能使代码更难以遵循,例如继承,构造函数,注释,泛型等等。

包装

Go允许将相关代码分组到包中。 编译时,程序包共享一个名称空间。 因此,您可以在单独的文件中编写代码,但是仍然可以调用位于不同目录或文件中的代码。 随着项目的复杂性增加,您可以创建许多软件包,每个软件包代表应用程序的不同逻辑单元。 但是,对于软件包,我们使用了一个特殊的名称来告诉Go我们希望将其转换为可以执行的文件。 该名称是“ main”

因此,将包命名为“ main”将告诉Go我们希望其可执行。 一旦Go知道该文件是可执行文件,它将需要我们定义一个名为“ main”的函数。 程序运行时,将自动调用此main功能。

Go有一个非常强大的标准库。 为了访问,我们只需在包声明下方添加import语句。 入门应该看起来像这样:

package main
import (
    "fmt"
)
func main() {
    fmt.Println("Hello world") // Amazing logic here
}
变数

在Go中使用变量很熟悉,但又有所不同。 让我们研究一下变量赋值,稍后我们将研究按值与按引用使用变量。 这是在Go中初始化变量的有效方法。

var currentDay string = “Saturday”

在一个示例中,它看起来像这样:

但这很冗长。 Go允许将变量声明和赋值简化为:

currentDay := “Saturday”

在这里可以推断出“ currentDay”是一个字符串,因此无需对其进行明确说明。 同样,Go理解以下是一个“ Integer”声明。

luckyNumber := 3

因此,以下两种是声明和初始化Go变量的等效方法。

luckyNumber := 3
var luckyNumber int = 3 // oops! This will cause an error!

不过要小心! 在Go中,我们只能将变量初始化一次。 因此,以上代码片段将无法编译!

功能

Go是一种静态类型的编程语言,因此我们需要为每个函数注释返回值的类型。 以下代码将无法编译,因为我们尚未注释返回类型:

func greetUser() { // function declaration is missing return type!
  return “Hey friend!”
}

要解决此错误,我们只需在函数声明中添加返回类型。

从main方法内部调用此函数如下所示:

凉。 让我们来看一个示例,其中我们将到目前为止所看到的一切都捆绑在一起。 让我们在不同的文件中声明greetUser,但是使用相同的包并调用它。 回想一下,同一包中的文件共享一个名称空间,并且可以自由地相互调用。

我们用

go run utils.go main.go

我们得到以下内容:

从我们的标准输出
切片和for循环

在Go中,数组是静态的,创建时需要指定其长度。 如果您想使用动态大小的数组,则需要使用slice 。 声明切片很简单:

fruits := []string{“Mango”, “Cherry”, “Apple”}

请注意,切片中只能包含一种类型的值。 因此,用一个int以及一个字符串声明一个切片将无法编译。

现在让我们对水果切片进行基本迭代并记录每个元素。

Don’t forget to build with go run main.go

一个陷阱是Go要求我们在代码中使用所有声明的变量。 如果我们不希望该索引,则可以通过将其命名为“下划线”来告诉Go忽略它,如下所示:

切片如何在引擎盖下工作

Go如何处理创建这些动态切片? Go的方法很有趣。 创建切片时,将在后台创建两个数据结构 。 第一个是数组,第二个是记录切片的长度,切片的容量以及对该数组的引用的结构。

是一种面向对象的语言吗?

根据文档“是”和“否”(是的,一个明确的答案!)。 Go采用不同的方法来尝试获得相似的结果。 在Go中,没有“类”。 相反,Go允许我们为特定数据类型声明“接收器函数”。 理解这一点的最简单方法是看一些代码。

因此,尽管我们无法创建Day类(就像现在使用经典的OOP语言一样-如今想想使用Java,Python甚至是JS),我们仍然可以轻松地声明这些类型的新数据类型和方法。

因此,让我们桥接Go术语并将其与经典OOP中的内容进行比较。

通过使用具有接收器的函数创建新的类型,我们将向该类型的任何值添加“方法”。 (斯蒂芬·格莱德)
多个返回值

我在Go中真正喜欢的功能是能够从一个函数返回多个值。 让我们在实践中看一下:

结构

Go的结构是可变字段的类型化集合 。 如果您来自JS,python或Java,那么它实际上是一个对象。 它们对于将数据分组在一起以形成记录很有用。

地址和指针

Go区分两种不同的数据类型。

值类型 -包含原始数据类型的实际值的类型。 考虑一下int,float,string等。

引用类型 -包含对实际基础记录列表的引用的任何数据类型。

这是对话开始变得更加有趣的地方。 默认情况下, 当将参数类型(例如int,float,string或struct)传递给函数时,Go复制每个参数并按值传递它。 有了这些知识,以下示例将按价值传递。 您希望它打印什么?

因为Go复制了“值类型”,并且没有向它们发送以上输出的引用:

我们刚刚看到Go中的变量是按值传递的。 就像我们前面提到的那样,当创建切片时,将创建一个在切片上具有元数据的附加数据结构。 这包括对slice的引用。 每当我们谈论切片时,都会使用并引用该引用。 因此,以下示例将成功使切片的内容发生变异。

但是,如果我们想对发送给函数的结构数据进行突变会怎样? 我们需要通过引用。 Go在这个概念上有点低级,要求我们传递变量的地址和取消引用指针。

除了:指针只是计算机内存中变量的地址。 如果发送变量的地址而不是值,则可以直接对其进行操作。
获取变量的地址

我们始终可以使用&运算符来获取变量的地址

这将输出物理内存中变量实际地址

现在,我们已经有了对变量(其地址)的引用我们可以轻松地通过取消引用指针并分配一些新值来更改其值。

另外: 取消引用是从地址中提取值的动作。 我们用*运算符取消引用地址。

因此,如果我们希望我们的函数接收一个指向日类型的指针(上一个示例中的结构) ,然后记录其值,我们将尝试执行以下操作:

让我们看一个使用接收器函数时按引用传递的示例。

那么为什么现在可以工作呢? 我们更改了updateDaySuccess接收器函数,以接受指向day类型的指针。

重要:调用方法时,Go会识别出它正在期待一个指针,并隐式地为我们发送对该值的引用(谢谢Go!)。然后,updateDaySuccess接收该指针,并使用*运算符对其进行取消引用,并分配一个新值。
地图

哈希表是最有用的数据结构之一。 它们提供快速查找,添加和删除。 Go提供了实现哈希表的内置映射类型。 在Go中,键和值可以是带有空接口的几种不同类型。 在该“转到游乐场”链接中,声明了具有几种不同类型的键的地图。 除此之外,它们的工作原理与您对它们的期望也非常相似。

介面

Go中的接口使代码更加灵活。 接口无需要求特定的类型,而是允许我们指定需要某些行为。 在Go中,接口是隐式满足的。 这意味着我们无需编写诸如blahBlah之类的东西 (我在看Java ppl) 当我们说类型满足接口时,是指该类型实现该接口定义中包含的所有功能。 让我们看一个基本的例子:

因此,在这里我们可以说day结构体满足dayDetails接口,因为它定义了返回字符串的接收器函数getDay。 因此,如果您遇到了其他任何语言的界面,其原理和优点都将延续到Go中。

goroutine

goroutine是与其他功能或方法同时运行的功能(接收器或常规)。 goroutine本质上是一个线程,但是开销较小。 因为goroutine比线程轻,所以go程序通常要同时运行数千个例程。 启动goroutine很简单! 只需在go关键字前面加上,就会自动使go例程同时运行。 尽管启动围棋例程很简单,但还是有一些陷阱。 让我们来看这个例子:

您期望输出是什么?

为什么没有输出“星期六”?

创建新的go例程后,调用将立即返回。 与函数不同, 控件不等待goroutine完成执行。 因此,在这种情况下,程序流程将继续并结束,主程序将自行终止并拥有其所拥有的goroutine。 让我们通过Hibernate程序来克服这个问题。 这将使我们的goroutine有足够的时间来完成执行。

这是可行的,但是超级hacky,而不是我们应该采用的做法。 渠道让我们做得更好。

频道

因此,我们已经看到生成go例程很容易。 通道是允许goroutine进行通信的工具。 通道允许我们将数据从一个goroutine传送到另一个goroutine(甚至使用pipe运算符!)。 每个通道都有与之关联的数据类型。 与通道关联的数据类型定义了我们可以通过其管道传输的数据。 例如,以下通道允许可以发送和接收布尔值:

boolChannel := make(chan bool)

通过通道发送和接收数据是阻止操作,因此我们可以轻松地重写上面的程序,而无需担心睡眠不足。

让我们看看重写我们的程序!

结论

这是Go功能的快速概述。 显然,这是冰山一角,还有很多发现:)我对Go的最初印象是它简洁而强大。 最近,我更喜欢使用静态类型的语言,因为它允许更快地开发,没有运行时错误,并且消除了整类的耗时错误! 我有兴趣学习Go来了解与区块链相关的项目,服务器以及任何需要并发的事物,因为它看起来既有趣又强大!

我的下一篇文章将探索区块链和Go,敬请期待!

如果此帖子有帮助,请订阅并单击下面的拍手👏按钮以显示您的支持! ⬇⬇

您可以在InstagramLinkedinMedium上关注我。

翻译自: https://hackernoon.com/time-to-go-learning-golang-through-examples-480a90c5e7f9

golang !

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值