适用于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还有更多的迭代方式,例如 whileforEachfor infor 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运算符 ...numsnums ...int

结论

在这一部分中,我们看到了两种语言中相似的概念。在本系列的下一部分中,我们将看到JS和Go之间的不同之处。下一部分将有更多不同之处,但也请注意,有些差异非常微妙,因此对于JavaScript开发人员来说很容易消化。

在下一章中,我们将看到:

  • 类型和变量
  • 错误处理
  • 变异性
  • 组成而不是继承
  • 并发
  • 汇编
  • 范例

参考文献:

  • http://www.pazams.com/Go-for-Javascript-开发工程师s/
  • https://github.com/miguelmota/golang-for-nodejs-developers

如果您喜欢这篇文章,请留下喜欢或评测。

您可以在Twitter和LinkedIn上关注我。

资讯来源:由0x资讯编译自DEV,原文:https://dev.to/deepu105/golang-for-javascript-developers-part-1-38je ,版权归作者所有,未经许可,不得转载
你可能还喜欢