适用于JavaScript开发人员的Golang-第1部分
请在Twitter上关注我以获取更新,并让我知道该帖子中可以改进的地方。
如果您是JavaScript开发人员,正在考虑学习另一种编程语言,那么Golang是一个不错的选择。它简单,动力十足,非常高效,并且与JavaScript有一些相似之处。
这篇文章不是对语言的比较,或者说它们非常相似。它是JavaScript开发人员快速掌握Golang的指南。 Go的许多方面与JavaScript完全不同,我们也会对此进行介绍。
更相似的东西
Go中有很多东西与JavaScript中的概念非常相似。大多数不完全相同,但相似。让我们先摆脱它们。在本系列的第一部分中,我们将看到它们的相似之处,并注意所有关键区别。
功能
JS和Go中最相似的功能是函数。
相似点
- 职能是一等公民。
- 可以将功能分配给变量。
- 函数可以作为参数传递给其他函数,也可以从函数中返回。
- 函数可以嵌套。
- 可以使用函数(部分函数)。
- 函数可以记住其周围的上下文,从而创建闭包。
- 函数可以命名或匿名。匿名函数可以立即被调用(IIFE)
的JavaScript
// A normal function with access to `this`
function standardFunction(arg1, arg2) {
return `${arg1}:${arg2}`;
}
// A function assigned to a variable
const assignedFunction1 = standardFunction;
// An arrow function assigned to a variable
const assignedArrowFunction = (arg1, arg2) => {
return `${arg1}:${arg2}`;
};
// A higher-order-function that accepts functions as argument and returns a function
function functionAsArgumentAndReturn(addFn, arg1, arg2) {
const out = addFn(arg1, arg2);
// This returns a closure
return function(numArg) {
return out + numArg;
};
}
const out = functionAsArgumentAndReturn(
(a, b) => {
return a + b;
},
5,
10
)(10);
// returns 25
// Nested functions
function nested() {
console.log("outer fn");
function nested2() {
console.log("inner fn");
const arrow = () => {
console.log("inner arrow");
};
arrow();
}
nested2();
}
nested(); // prints:
// outer fn
// inner fn
// inner arrow
// this is a higher-order-function that returns a function
function add(x) {
// A function is returned here as closure
// variable x is obtained from the outer scope of this method and memorized in the closure
return y => x + y;
}
// we are currying the add method to create more variations
var add10 = add(10);
var add20 = add(20);
var add30 = add(30);
console.log(add10(5)); // 15
console.log(add20(5)); // 25
console.log(add30(5)); // 35
// An anonymous function invoked immediately(IIFE)
(function() {
console.log("anonymous fn");
})();
// prints: anonymous fn
走
// A normal function, this cannot be nested
func standardFunction(arg1 string, arg2 string) string {
return fmt.Sprintf("%s:%s", arg1, arg2)
}
func main() {
// A function assigned to a variable
var assignedFunction1 = standardFunction
// An anonymous function assigned to a variable and nested
var assignedFunction2 = func(arg1 string, arg2 string) string {
return fmt.Sprintf("%s:%s", arg1, arg2)
}
// A higher-order-function that accepts functions as argument and returns a function
var functionAsArgumentAndReturn = func(addFn func(int, int) int, arg1 int, arg2 int) func(int) int {
var out = addFn(arg1, arg2)
// This returns a closure
return func(numArg int) int {
return out + numArg
}
}
var out = functionAsArgumentAndReturn(
func(a, b int) int {
return a + b
},
5,
10,
)(10)
fmt.Println(out) // prints 25
// Nested anonymous functions
var nested = func() {
fmt.Println("outer fn")
var nested2 = func() {
fmt.Println("inner fn")
var nested3 = func() {
fmt.Println("inner arrow")
}
nested3()
}
nested2()
}
nested() // prints:
// outer fn
// inner fn
// inner arrow
// this is a higher-order-function that returns a function
var add = func(x int) func(y int) int {
// A function is returned here as closure
// variable x is obtained from the outer scope of this method and memorized in the closure
return func(y int) int {
return x + y
}
}
// we are currying the add method to create more variations
var add10 = add(10)
var add20 = add(20)
var add30 = add(30)
fmt.Println(add10(5)) // 15
fmt.Println(add20(5)) // 25
fmt.Println(add30(5)) // 35
// An anonymous function invoked immediately(IIFE)
(func() {
fmt.Println("anonymous fn")
})()
// prints: anonymous fn
assignedFunction1("a", "b")
assignedFunction2("a", "b")
}
差异性
- JavaScript函数有两种形式:常规功能和箭头功能,而在Go中包含常规功能和界面功能。普通的Go功能没有
this
因此与箭头功能更相似,而界面功能与this
因此更接近JavaScript中的正常功能。 Go没有全球化的概念this
。
的JavaScript
function normalFnOutsideClass() {
console.log(`I still can access global this: ${this}`);
}
const arrowFnOutsideClass = () => {
console.log(`I don't have any this`);
};
class SomeClass {
name = "Foo";
normalFnInsideClass = function() {
console.log(`I can access the callee as this: ${this.name}`);
};
arrowFnInsideClass = () => {
console.log(`I can access the class reference as this: ${this.name}`);
};
}
new SomeClass().normalFnInsideClass();
new SomeClass().arrowFnInsideClass();
走
type SomeStruct struct {
name string
}
func (this *SomeStruct) normalFnInsideStruct() {
// you can name the variable this or anything else
fmt.Printf("I can access the struct reference as thisn: %s", this.name)
}
func main() {
var normalFnOutsideStruct = func() {
fmt.Println("I can access variables in my scope")
}
normalFnOutsideStruct()
var structVal = SomeStruct{"Foo"}
structVal.normalFnInsideStruct()
}
- JavaScript函数与任何其他值类型相同,因此甚至可以包含Go中不可能的其他属性。
- Go函数可以具有隐式命名返回。
- Go中只能嵌套匿名函数。
- Go函数可以返回多个值,而在JavaScript中,您只能返回一个值。但是,在JS中,您可以通过使用分解来解决此问题,因此您可以在两者中执行相似的功能
的JavaScript
function holdMyBeer() {
return ("John", 2);
}
let (a, b) = holdMyBeer();
console.log(`Hey ${a}, hold my ${b} beern`);
走
func holdMyBeer() (string, int64) {
return "John", 2
}
func main() {
a, b := holdMyBeer()
fmt.Printf("Hey %s, hold my %d beern", a, b)
}
范围
作用域是变量有效的上下文,它决定了可以在哪里使用变量,并且JS和Go在这里有很多相似之处
相似点
- 两者都有功能范围,而功能可以记住其周围的范围。
- 两者都有块范围。
- 两者都有全球范围。
差异性
- 去没有概念
this
这是JavaScript中的一个棘手的概念。 IMO这使Go中的事情变得更加简单。 - 同一范围内的变量不能在Go中重新声明。走
var
更接近let
JS中的关键字。
流量控制
Golang中的流控制在很多方面都非常相似,但比JavaScript更简单。
相似点
-
for
两者的循环非常相似。 -
while
循环非常相似,尽管Go使用相同的for
关键词。 -
forEach
在功能上也相似,但语法完全不同。 - 您可以从循环中中断/继续。
-
if/else
语法非常相似,Go版本功能更强大
的JavaScript
// For loop
for (let i = 0; i < 10; i++) {
console.log(i);
}
// While loop
let i = 0;
while (i < 10) {
console.log(i);
i++;
}
// Do while
let j = 0;
do {
j += 1;
console.log(j);
} while (j < 5);
// ForEach loop
("John", "Sam", "Ram", "Sabi", "Deepu").forEach((v, i) => {
console.log(`${v} at index ${i}`);
});
// for of loop
for (let i of ("John", "Sam", "Ram", "Sabi", "Deepu")) {
console.log(i);
}
// For in loop
const obj = {
a: "aVal",
b: "bVal"
};
for (let i in obj) {
console.log(obj(i));
}
走
func main() {
// For loop
for i := 0; i < 10; i++ {
fmt.Println(i)
}
// While loop
i := 0
for i < 10 {
fmt.Println(i)
i++
}
// Do while
j := 0
for {
j += 1
fmt.Println(j)
if j == 5 {
break
}
}
// ForEach and for of loop
for i, v := range ()string{"John", "Sam", "Ram", "Sabi", "Deepu"} {
fmt.Printf("%v at index %dn", v, i)
}
// For in loop
var obj = map(string)string{
"a": "aVal",
"b": "bVal",
}
for i, v := range obj {
fmt.Printf("%v at index %sn", v, i)
}
}
差异性
- Go中没有三元运算符。
-
if/else
可以在Go中进行初始化分配。 -
switch
语句语法相似,但是Go默认会中断,而JS默认会失败。在Go中,您可以使用fallthrough
该功能的关键字,而在JS中,break
关键词。 - JS还有更多的迭代方式,例如
while
,forEach
,for in
和for of
循环等在Go中不可用,尽管大多数循环可以使用for
句法。 - Go中没有标记的中断。
走
if val := getVal(); val < 10 {
return val
} else {
return val + 1
}
这在JS中是不可能的
内存管理
内存管理也非常相似,除了JS和Go中的细节。
相似点
- 两者都是在运行时收集的垃圾。
- 两者都有堆和堆栈内存,这意味着两者相同。
差异性
- Go的指针在用户的内存管理被抽象化时向用户公开,而在JavaScript中,指针被完全抽象化,并且您只能使用值和引用。
- Go使用并发的三色Mark-sweep算法,其重点是等待时间,而JS引擎通常实现不同的算法,其中Mark-Sweep是一个非常受欢迎的选择。例如,V8引擎同时使用了Mark-Sweep和Scavenge算法。
杂项
- 两者的评测相同,
//
和/* */
- JS和Go都支持导入其他模块,尽管其行为并不完全相同
- SetTimeout两者相似。
setTimeout(somefunction, 3*1000)
与time.AfterFunc(3*time.Second, somefunction)
。 - 两者都有点差运算符
console.log(...array)
与fmt.Println(array...)
。不过,“传播”仅适用于接口阵列/切片。 - 两者都有用于方法参数的rest运算符
...nums
与nums ...int
。
结论
在这一部分中,我们看到了两种语言中相似的概念。在本系列的下一部分中,我们将看到JS和Go之间的不同之处。下一部分将有更多不同之处,但也请注意,有些差异非常微妙,因此对于JavaScript开发人员来说很容易消化。
在下一章中,我们将看到:
- 类型和变量
- 错误处理
- 变异性
- 组成而不是继承
- 并发
- 汇编
- 范例
参考文献:
- http://www.pazams.com/Go-for-Javascript-开发工程师s/
- https://github.com/miguelmota/golang-for-nodejs-developers
如果您喜欢这篇文章,请留下喜欢或评测。
您可以在Twitter和LinkedIn上关注我。