Golang для разработчиков Node.js
(исходный код с открытым исходным кодом: https://github.com/miguelmota/golang-for-nodejs-developers - я добавил и изменил множество примеров для большего контекста, краткости и идиоматичности JS)
Добавлю примеры WebAssembly - так что возвращайся!
Это руководство, полное примеров, предназначено для людей, изучающих Go с Node.js, хотя может работать и обратное. Это не является полным руководством, и предполагается, что вы уже прошли курс Tour of Go. Это руководство предназначено только для того, чтобы помочь вам на высоком уровне понять, как выполнять X в Y, и, конечно же, требуется дальнейшее обучение самостоятельно.
СОДЕРЖАНИЕ
- "Примеры"
- "Комментарии"
- Печать
- "протоколирование"
- Переменные
- Интерполяция
- Типы
- Проверка типа
- "если еще"
- Тройной
- "для"
- "в то время как"
- "выключатель"
- Массивы
- Массивы uint8
- Итерация массива
- Буферы
- Карты
- "объекты"
- Функции
- "значения по умолчанию"
- Деструктуризация
- Оператор распространения
- Оператор отдыха
- Свопинг
- Классы
- Генераторы
- Дата и время
- Тайм-аут
- Интервал
- IIFE
- Файлы
- Json
- Большие числа
- uint
- Обещания
- Асинхронный / ожидающий
- Потоки
- Эмиттер событий
- Ошибки
- "попробуй поймать"
- Исключения
- Регулярное выражение
- Exec (синхронизация)
- Exec (асинхронный)
- Tcp сервер
- Сервер UDP
- Http сервер
- Парсинг URL
- Gzip
- Днс
- Крипто
- Env vars
- Cli args
- Cli flags
- Стандартный вывод
- Stderr
- Стандартный ввод
- Модули
- "трассировки стека"
- Базы данных
- Тестирование
- Бенчмаркинг
- "документация"
Примеры
Весь пример кода доступен в examples /
Комментарии
Node.js
// this is a line comment
/* this is a block comment */
Go
package main func main() { // this is a line comment /* this is a block comment */ }
Печать
Node.js
console.log('print to stdout')
// string specifier (%s) - passes argument to String() constructor // number specifier (%d) - passes argument to Number() constructor console.log('format %s %d', 'example', 1) console.log('format %s %d', 'example', false) console.log('format %s %d', 'example', 'ok')
// parse float specifier (%f) console.log('format %s %f', 'example', 'this is 1.23') // parse int specifier (%i) console.log('format %s %i', 'example', 'this is 1.23') // stringify to JSON specifier (%j) console.log('format %s %j', 'example', {a:1, b: 2}) // stringify object specifier (%o) - with non-enumerable properties console.log('format %s %o', 'example', {a:1, b: 2, c: ['ok','ko']}) // stringify object specifier (%O) - without non-enumerable props console.log('format %s %O', 'example', {a:1, b: 2, c: ['ok','ko']}) // positional arguments console.log( 'format %s %[2]s is an %[1]', 'example', 'engineer','Jason' )console.error('print to stderr')
process.stdout.write('print to stdout too
') process.stderr.write('print to stderr too')
Выход
print to stdout format example 1 format example 0 format example NaN format example 1.23 format example 1 format example { a: 1, b: 2, c: [ 'ok', 'ko', [length]: 2 ] } format example { a: 1, b: 2, c: [ 'ok', 'ko' ] } format example Jason is an engineer print to stderr print to stdout too print to stderr too
Go
package main import ( "fmt" "os" ) func main() { fmt.Println("print to stdout") fmt.Printf("format %s %v\n", "example", 1) fmt.Printf("format %s %v\n", "example", false) fmt.Fprintf(os.Stderr, "print to stderr") }
Выход
print to stdout format example 1 print to stderr
логирование
Node.js
console.log((new Date()).toISOString(), 'hello world')
Выход
2021-04-11T20:55:07.451Z hello world
Go
package main import "log" func main() { log.Println("hello world") }
Выход
2021/04/11 13:55:07 hello world
(Пакет log
записывает стандартную ошибку и печатает дату и время каждого зарегистрированного сообщения)
Переменные
Node.js
// function scoped // callable before declaration (variable hoisting) var foo = 'foo'
// block scoped // not callable before declaration (temporal dead zone) let bar = 'bar'
// constant (no reassignment) // block scoped (not callable before declaration) const qux = 'qux'
Go
(переменные в Go ограничены блоком)
package main func main() { // explicit var foo string = "foo" // type inferred var bar = "foo" // shorthand baz := "bar" // constant const qux = "qux" }
Интерполяция
Node.js
const name = 'bob' const age = 21 const message = `${name} is ${age} years old`
console.log(message)
Выход
bob is 21 years old
Go
package main import "fmt" func main() { name := "bob" age := 21 message := fmt.Sprintf("%s is %d years old", name, age) fmt.Println(message) }
Выход
bob is 21 years old
Типы
Node.js
// primitives const myBool = true const myNumber = 10 const myString = 'foo' const mySymbol = Symbol('bar') const myNull = null const myUndefined = undefined
// object types const myObject = {} const myArray = [] const myFunction = function() {} const myError = new Error('error') const myDate = new Date() const myRegex = /a/ const myMap = new Map() const mySet = new Set() const myPromise = Promise.resolve() const myGenerator = function *() {} const myClass = class {}
Go
package main func main() { // primitives var myBool bool = true var myInt int = 10 var myInt8 int8 = 10 var myInt16 int16 = 10 var myInt32 int32 = 10 var myInt64 int64 = 10 var myUint uint = 10 var myUint8 uint8 = 10 var myUint16 uint16 = 10 var myUint32 uint32 = 10 var myUint64 uint64 = 10 var myUintptr uintptr = 10 var myFloat32 float32 = 10.5 var myFloat64 float64 = 10.5 var myComplex64 complex64 = -1 + 10i var myComplex128 complex128 = -1 + 10i var myString string = "foo" var myByte byte = 10 // alias to uint8 var myRune rune = 'a' // alias to int32 // composite types var myStruct struct{} = struct{}{} var myArray []string = []string{} var myMap map[string]int = map[string]int{} var myFunction func() = func() {} var myChannel chan bool = make(chan bool) var myInterface interface{} = nil // pointer: points to location in memory where value stored // notice the asterisk (*) before the type var myPointer *int = new(int) }
Тип проверки
Node.js
function typeOf(obj) { return ({}).toString.call(obj) .split(' ')[1].slice(0,-1).toLowerCase() }
const values = [ true, 10, 'foo', Symbol('bar'), null, undefined, NaN, {}, [], function(){}, new Error(), new Date(), /a/, new Map(), new Set(), Promise.resolve(), function *() {}, class {}, 23n, ]
values.forEach(value => console.log( typeOf(value) ) )
Выход
boolean number string symbol null undefined number object array function error date regexp map set promise generatorfunction function bigint
Go
package main import ( "fmt" "reflect" "regexp" "time" ) func main() { values := []interface{}{ true, int8(10), int16(10), int32(10), int64(10), uint(10), uint8(10), uint16(10), uint32(10), uint64(10), uintptr(10), float32(10.5), float64(10.5), complex64(-1 + 10i), complex128(-1 + 10i), "foo", byte(10), 'a', rune('a'), struct{}{}, []string{}, map[string]int{}, func() {}, make(chan bool), nil, new(int), time.Now(), regexp.MustCompile(`^a$`), } for _, value := range values { fmt.Println(reflect.TypeOf(value)) } }
Выход
bool int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr float32 float64 complex64 complex128 string uint8 int32 int32 struct {} []string map[string]int func() chan bool <nil> *int time.Time *regexp.Regexp
Если еще
Node.js
const array = [1, 2]
if (array) { console.log('array exists') }
if (array.length === 2) { console.log('length is 2') } else if (array.length === 1) { console.log('length is 1') } else { console.log('length is other') }
const isOddLength = array.length % 2 == 1 ? 'yes' : 'no'
console.log(isOddLength)
Выход
array exists length is 2 no
Go
package main import "fmt" func main() { array := []byte{1, 2} if array != nil { fmt.Println("array exists") } if len(array) == 2 { fmt.Println("length is 2") } else if len(array) == 1 { fmt.Println("length is 1") } else { fmt.Println("length is other") } // closest thing to ternary operator isOddLength := "no" if len(array)%2 == 1 { isOddLength = "yes" } fmt.Println(isOddLength) }
Выход
array exists length is 2 no
Для
Node.js
for (let i = 0; i <= 5; i++) {
console.log(i)
}
Выход
0 1 2 3 4 5
Go
package main import "fmt" func main() { for i := 0; i <= 5; i++ { fmt.Println(i) } }
Выход
0 1 2 3 4 5
В то время как
Node.js
let i = 0
while (i <= 5) { console.log(i)
i++ }
Выход
0 1 2 3 4 5
Go
(в Go нет ключевого слова while, но та же функциональность достигается за счет использования for)
package main import "fmt" func main() { i := 0 for i <= 5 { fmt.Println(i) i++ } }
Выход
0 1 2 3 4 5
Выключатель
Node.js
const value = 'b'
switch(value) { case 'a': console.log('A') break case 'b': console.log('B') break case 'c': console.log('C') break default: console.log('first default') }
switch(value) { case 'a': console.log('A - falling through') case 'b': console.log('B - falling through') case 'c': console.log('C - falling through') default: console.log('second default') }
Выход
B B - falling through C - falling through second default
Go
package main import "fmt" func main() { value := "b" switch value { case "a": fmt.Println("A") case "b": fmt.Println("B") case "c": fmt.Println("C") default: fmt.Println("first default") } switch value { case "a": fmt.Println("A - falling through") fallthrough case "b": fmt.Println("B - falling through") fallthrough case "c": fmt.Println("C - falling through") fallthrough default: fmt.Println("second default") } }
Выход
B B - falling through C - falling through second default
Массивы
Примеры нарезки, копирования, добавления и добавления массивов.
Node.js
const array = [1, 2, 3, 4, 5] console.log(array)
const clone = array.slice(0) console.log(clone)
const sub = array.slice(2,4) console.log(sub)
const concatenated = clone.concat([6, 7]) console.log(concatenated)
const prepended = [-2,-1,0].concat(concatenated) console.log(prepended)
Выход
[ 1, 2, 3, 4, 5 ] [ 1, 2, 3, 4, 5 ] [ 3, 4 ] [ 1, 2, 3, 4, 5, 6, 7 ] [ -2, -1, 0, 1, 2, 3, 4, 5, 6, 7 ]
Go
package main import "fmt" func main() { array := []int{1, 2, 3, 4, 5} fmt.Println(array) clone := make([]int, len(array)) copy(clone, array) fmt.Println(clone) sub := array[2:4] fmt.Println(sub) concatenated := append(array, []int{6, 7}...) fmt.Println(concatenated) prepended := append([]int{-2, -1, 0}, concatenated...) fmt.Println(prepended) }
Выход
[1 2 3 4 5] [1 2 3 4 5] [3 4] [1 2 3 4 5 6 7] [-2 -1 0 1 2 3 4 5 6 7]
Массивы Uint8
Node.js
const array = new Uint8Array(10) console.log(array) const offset = 1 array.set([1, 2, 3], offset) console.log(array) const sub = array.subarray(2) console.log(sub) const sub2 = array.subarray(2,4) console.log(sub2) console.log(array) const value = 9 const start = 5 const end = 10 array.fill(value, start, end) console.log(array) console.log(array.byteLength)
Выход
Uint8Array [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] Uint8Array [ 0, 1, 2, 3, 0, 0, 0, 0, 0, 0 ] Uint8Array [ 2, 3, 0, 0, 0, 0, 0, 0 ] Uint8Array [ 2, 3 ] Uint8Array [ 0, 1, 2, 3, 0, 0, 0, 0, 0, 0 ] Uint8Array [ 0, 1, 2, 3, 0, 9, 9, 9, 9, 9 ] 10
Go
package main import "fmt" func main() { array := make([]uint8, 10) fmt.Println(array) offset := 1 copy(array[offset:], []uint8{1, 2, 3}) fmt.Println(array) sub := array[2:] fmt.Println(sub) sub2 := array[2:4] fmt.Println(sub2) fmt.Println(array) value := uint8(9) start := 5 end := 10 for i := start; i < end; i++ { array[i] = value } fmt.Println(array) fmt.Println(len(array)) }
Выход
[0 0 0 0 0 0 0 0 0 0] [0 1 2 3 0 0 0 0 0 0] [2 3 0 0 0 0 0 0] [2 3] [0 1 2 3 0 0 0 0 0 0] [0 1 2 3 0 9 9 9 9 9] 10
Итерация массива
Примеры итерации, сопоставления, фильтрации и сокращения массивов.
Node.js
const array = ['a', 'b', 'c']
array.forEach((value, i) => { console.log(i, value) })
const mapped = array.map(value => { return value.toUpperCase() })
console.log(mapped)
const filtered = array.filter((value, i) => { return i % 2 == 0 })
console.log(filtered)
const reduced = array.reduce((acc, value, i) => { if (i % 2 == 0) { acc.push(value.toUpperCase()) }
return acc }, [])
console.log(reduced)
Выход
0 'a' 1 'b' 2 'c' [ 'A', 'B', 'C' ] [ 'a', 'c' ] [ 'A', 'C' ]
Go
package main import ( "fmt" "strings" ) func main() { array := []string{"a", "b", "c"} for i, value := range array { fmt.Println(i, value) } mapped := make([]string, len(array)) for i, value := range array { mapped[i] = strings.ToUpper(value) } fmt.Println(mapped) var filtered []string for i, value := range array { if i%2 == 0 { filtered = append(filtered, value) } } fmt.Println(filtered) var reduced []string for i, value := range array { if i%2 == 0 { reduced = append(reduced, strings.ToUpper(value)) } } fmt.Println(reduced) }
Выход
0 a 1 b 2 c [A B C] [a c] [A C]
Сортировка массивов
Примеры сортировки массива
Node.js
const stringArray = ['a', 'd', 'z', 'b', 'c', 'y'] const stringArraySortedAsc = stringArray.sort((a, b) => a > b ? 1 : -1) console.log(stringArraySortedAsc)
const stringArraySortedDesc = stringArray.sort((a, b) => a > b ? -1 : 1) console.log(stringArraySortedDesc)
const numberArray = [1, 3, 5, 9, 4, 2, 0] const numberArraySortedAsc = numberArray.sort((a, b) => a - b) console.log(numberArraySortedAsc)
const numberArraySortedDesc = numberArray.sort((a, b) => b - a) console.log(numberArraySortedDesc)
const collection = [ { name: "Li L", age: 8 }, { name: "Json C", age: 3 }, { name: "Zack W", age: 15 }, { name: "Yi M", age: 2 } ]
const collectionSortedByAgeAsc = collection.sort((a, b) => a.age - b.age) console.log(collectionSortedByAgeAsc)
const collectionSortedByAgeDesc = collection.sort((a, b) => b.age - a.age) console.log(collectionSortedByAgeDesc)
Выход
[ 'a', 'b', 'c', 'd', 'y', 'z' ] [ 'z', 'y', 'd', 'c', 'b', 'a' ] [ 0, 1, 2, 3, 4, 5, 9 ] [ 9, 5, 4, 3, 2, 1, 0 ] [ { name: 'Yi M', age: 2 }, { name: 'Json C', age: 3 }, { name: 'Li L', age: 8 }, { name: 'Zack W', age: 15 } ] [ { name: 'Zack W', age: 15 }, { name: 'Li L', age: 8 }, { name: 'Json C', age: 3 }, { name: 'Yi M', age: 2 } ]
Go
package main import ( "fmt" "sort" ) type Person struct { Name string Age int } type PersonCollection []Person func (pc PersonCollection) Len() int { return len(pc) } func (pc PersonCollection) Swap(i, j int) { pc[i], pc[j] = pc[j], pc[i] } func (pc PersonCollection) Less(i, j int) bool { // asc return pc[i].Age < pc[j].Age } func main() { intList := []int{1, 3, 5, 9, 4, 2, 0} // asc sort.Ints(intList) fmt.Println(intList) // desc sort.Sort(sort.Reverse(sort.IntSlice(intList))) fmt.Println(intList) stringList := []string{"a", "d", "z", "b", "c", "y"} // asc sort.Strings(stringList) fmt.Println(stringList) // desc sort.Sort(sort.Reverse(sort.StringSlice(stringList))) fmt.Println(stringList) collection := []Person{ {"Li L", 8}, {"Json C", 3}, {"Zack W", 15}, {"Yi M", 2}, } // asc sort.Sort(PersonCollection(collection)) fmt.Println(collection) // desc sort.Sort(sort.Reverse(PersonCollection(collection))) fmt.Println(collection) }
Выход
[0 1 2 3 4 5 9] [9 5 4 3 2 1 0] [a b c d y z] [z y d c b a] [{Yi M 2} {Json C 3} {Li L 8} {Zack W 15}] [{Zack W 15} {Li L 8} {Json C 3} {Yi M 2}]
Буферы
Примеры того, как выделить буфер, записать в формате с прямым или обратным порядком байтов, закодировать в шестнадцатеричную строку и проверить, равны ли буферы.
Node.js
const buf = Buffer.alloc(6)
let value = 0x1234567890ab let offset = 0 let byteLength = 6
buf.writeUIntBE(value, offset, byteLength)
let hexstr = buf.toString('hex') console.log(hexstr)
const buf2 = Buffer.alloc(6)
value = 0x1234567890ab offset = 0 byteLength = 6
buf2.writeUIntLE(value, offset, byteLength)
hexstr = buf2.toString('hex') console.log(hexstr)
let isEqual = Buffer.compare(buf, buf2) === 0 console.log(isEqual)
isEqual = Buffer.compare(buf, buf) === 0 console.log(isEqual)
Выход
1234567890ab ab9078563412 false true
Go
package main import ( "bytes" "encoding/binary" "encoding/hex" "fmt" "log" "math/big" "reflect" ) func writeUIntBE(buffer []byte, value, offset, byteLength int64) { slice := make([]byte, byteLength) val := new(big.Int) val.SetUint64(uint64(value)) valBytes := val.Bytes() buf := bytes.NewBuffer(slice) err := binary.Write(buf, binary.BigEndian, &valBytes) if err != nil { log.Fatal(err) } slice = buf.Bytes() slice = slice[int64(len(slice))-byteLength : len(slice)] copy(buffer[offset:], slice) } func writeUIntLE(buffer []byte, value, offset, byteLength int64) { slice := make([]byte, byteLength) val := new(big.Int) val.SetUint64(uint64(value)) valBytes := val.Bytes() tmp := make([]byte, len(valBytes)) for i := range valBytes { tmp[i] = valBytes[len(valBytes)-1-i] } copy(slice, tmp) copy(buffer[offset:], slice) } func main() { buf := make([]byte, 6) writeUIntBE(buf, 0x1234567890ab, 0, 6) fmt.Println(hex.EncodeToString(buf)) buf2 := make([]byte, 6) writeUIntLE(buf2, 0x1234567890ab, 0, 6) fmt.Println(hex.EncodeToString(buf2)) isEqual := reflect.DeepEqual(buf, buf2) fmt.Println(isEqual) isEqual = reflect.DeepEqual(buf, buf) fmt.Println(isEqual) }
Выход
1234567890ab ab9078563412 false true
Карты
Node.js
const map = new Map() map.set('foo', 'bar')
let found = map.has('foo') console.log(found)
let item = map.get('foo') console.log(item)
map.delete('foo')
found = map.has('foo') console.log(found)
item = map.get('foo') console.log(item)
const map2 = {} map2['foo'] = 'bar' item = map2['foo'] delete map2['foo']
const map3 = new Map() map3.set('foo', 100) map3.set('bar', 200) map3.set('baz', 300)
for (let [key, value] of map3) { console.log(key, value) }
Выход
true bar false undefined foo 100 bar 200 baz 300
Go
package main import "fmt" func main() { map1 := make(map[string]string) map1["foo"] = "bar" item, found := map1["foo"] fmt.Println(found) fmt.Println(item) delete(map1, "foo") item, found = map1["foo"] fmt.Println(found) fmt.Println(item) map2 := make(map[string]int) map2["foo"] = 100 map2["bar"] = 200 map2["baz"] = 300 for key, value := range map2 { fmt.Println(key, value) } }
Выход
true bar false foo 100 bar 200 baz 300
Объекты
Node.js
const obj = { someProperties: { 'foo': 'bar' }, someMethod: (prop) => { return obj.someProperties[prop] } }
let item = obj.someProperties['foo'] console.log(item)
item = obj.someMethod('foo') console.log(item)
Выход
bar bar
Go
package main import "fmt" type Obj struct { SomeProperties map[string]string } func NewObj() *Obj { return &Obj{ SomeProperties: map[string]string{ "foo": "bar", }, } } func (o *Obj) SomeMethod(prop string) string { return o.SomeProperties[prop] } func main() { obj := NewObj() item := obj.SomeProperties["foo"] fmt.Println(item) item = obj.SomeMethod("foo") fmt.Println(item) }
Выход
bar bar
Функции
Node.js
function add(a, b) { return a + b }
const result = add(2,3) console.log(result)
Выход
5
Go
package main import "fmt" func add(a int, b int) int { return a + b } func main() { result := add(2, 3) fmt.Println(result) }
Выход
5
Значения по умолчанию
Node.js
function greet(name = 'stranger') { return `hello ${name}` }
let message = greet() console.log(message)
message = greet('bob') console.log(message)
Выход
hello stranger hello bob
Go
используйте указатели и проверьте на ноль, чтобы узнать, явно ли оставлено пустым
package main import "fmt" func greet(name *string) string { n := "stranger" if name != nil { n = *name } return fmt.Sprintf("hello %s", n) } func main() { message := greet(nil) fmt.Println(message) name := "bob" message = greet(&name) fmt.Println(message) }
Выход
hello stranger hello bob
Деструктуризация
Node.js
const obj = { key: 'foo', value: 'bar' }
const { key, value } = obj console.log(key, value)
Выход
foo bar
Go
package main import "fmt" type Obj struct { Key string Value string } func (o *Obj) Read() (string, string) { return o.Key, o.Value } func main() { obj := Obj{ Key: "foo", Value: "bar", } // option 1: multiple variable assignment key, value := obj.Key, obj.Value fmt.Println(key, value) // option 2: return multiple values from a function key, value = obj.Read() fmt.Println(key, value) }
Выход
foo bar foo bar
Оператор распространения
Node.js
const array = [1, 2, 3, 4, 5]
console.log(...array)
Выход
1 2 3 4 5
Go
package main import "fmt" func main() { array := []byte{1, 2, 3, 4, 5} var i []interface{} for _, value := range array { i = append(i, value) } fmt.Println(i...) }
Выход
1 2 3 4 5
Оператор отдыха
Node.js
function sum(...nums) { let t = 0
for (let n of nums) { t += n }
return t }
const total = sum(1, 2, 3, 4, 5) console.log(total)
Выход
15
Go
package main import "fmt" func sum(nums ...int) int { var t int for _, n := range nums { t += n } return t } func main() { total := sum(1, 2, 3, 4, 5) fmt.Println(total) }
Выход
15
Обмен
Node.js
let a = 'foo' let b = 'bar'
console.log(a, b);
[b, a] = [a, b]
console.log(a, b)
Выход
foo bar bar foo
Go
package main import "fmt" func main() { a := "foo" b := "bar" fmt.Println(a, b) b, a = a, b fmt.Println(a, b) }
Выход
foo bar bar foo
Классы
Примеры классов, конструкторов, создания экземпляров и ключевого слова this.
Node.js
class Foo {
// private property#items #accessed = 0
constructor(value) { // public property this.item = value this.#items = [value]
}
// not really useful
unless other logic done when getting// because of implicit getter for public properties getItem() { this.#accessed++ return this.item }
// custom getter // overrides implicit getter if same name as public property get them() {return this.#items.join('/')
} // not really useful unless other logic done when setting // because of implicit setter for public propertiessetItem(value) { this.#items.push(value) this.item = value }
// custom setter // overrides implicit setter if same name as public property set them(value
) { this.#items.push(value) }}
const foo = new Foo('bar') console.log(foo.item)
foo.setItem('qux')
const item = foo.getItem() console.log(item)
// from implicit getter (public property) console.log(foo.item) // from custom getter (implicit call to function) console.log(foo.them) // from custom setter (implicit call to function with argument) foo.them = 'baz' console.log(foo.them)
Выход
bar qux qux bar/qux bar/qux/baz
Go
(самое близкое к классу - использовать структуру, известную как struct)
package main import "fmt" type Foo struct { Item string } func NewFoo(value string) *Foo { return &Foo{ Item: value, } } func (f *Foo) GetItem() string { return f.Item } func (f *Foo) SetItem(value string) { f.Item = value } func main() { foo := NewFoo("bar") fmt.Println(foo.Item) foo.SetItem("qux") item := foo.GetItem() fmt.Println(item) }
Выход
bar qux
Генераторы
Node.js
function *generator() { yield 'hello' yield 'world' }
let gen = generator()
while (true) { let { value, done } = gen.next() console.log(value, done)
if (done) { break } }
// alternatively for (let value of generator()) { console.log(value) }
Выход
hello false world false undefined true hello world
Go
package main import "fmt" func Generator() chan string { c := make(chan string) go func() { c <- "hello" c <- "world" close(c) }() return c } func GeneratorFunc() func() (string, bool) { s := []string{"hello", "world"} i := -1 return func() (string, bool) { i++ if i >= len(s) { return "", false } return s[i], true } } func main() { gen := Generator() for { value, more := <-gen fmt.Println(value, more) if !more { break } } // alternatively for value := range Generator() { fmt.Println(value) } // alternatively genfn := GeneratorFunc() for { value, more := genfn() fmt.Println(value, more) if !more { break } } }
Выход
hello true world true false hello world hello true world true false
Дата и время
Примеры синтаксического анализа, форматирования и получения временных меток дат в формате unix.
Node.js
const nowUnix = Date.now() console.log(nowUnix)
const datestr = '2019-01-17T09:24:23+00:00' const date = new Date(datestr) console.log(date.getTime()) console.log(date.toString())
const futureDate = new Date(date) futureDate.setDate(date.getDate()+14) console.log(futureDate.toString())
const formatted = `${String(date.getMonth()+1).padStart(2, 0)}/${String(date.getDate()).padStart(2, 0)}/${date.getFullYear()}` console.log(formatted)
Выход
1547718844168 1547717063000 Thu Jan 17 2019 01:24:23 GMT-0800 (Pacific Standard Time) Thu Jan 31 2019 01:24:23 GMT-0800 (Pacific Standard Time) 01/17/2019
Go
package main import ( "fmt" "time" ) func main() { nowUnix := time.Now().Unix() fmt.Println(nowUnix) datestr := "2019-01-17T09:24:23+00:00" date, err := time.Parse("2006-01-02T15:04:05Z07:00", datestr) if err != nil { panic(err) } fmt.Println(date.Unix()) fmt.Println(date.String()) futureDate := date.AddDate(0, 0, 14) fmt.Println(futureDate.String()) formatted := date.Format("01/02/2006") fmt.Println(formatted) }
Выход
1547718844 1547717063 2019-01-17 09:24:23 +0000 +0000 2019-01-31 09:24:23 +0000 +0000 01/17/2019
Тайм-аут
Node.js
setTimeout(callback, 1e3)
function callback() { console.log('called') }
Выход
called
Go
package main import ( "fmt" "sync" "time" ) var wg sync.WaitGroup func callback() { defer wg.Done() fmt.Println("called") } func main() { wg.Add(1) time.AfterFunc(1*time.Second, callback) wg.Wait() }
Выход
called
Интервал
Node.js
let i = 0
const id = setInterval(callback, 1e3)
function callback() { console.log('called', i)
if (i === 3) { clearInterval(id) }
i++ }
Выход
called 0 called 1 called 2 called 3
Go
package main import ( "fmt" "time" ) func callback(i int) { fmt.Println("called", i) } func main() { ticker := time.NewTicker(1 * time.Second) i := 0 for range ticker.C { callback(i) if i == 3 { ticker.Stop() break } i++ } }
Выход
called 0 called 1 called 2 called 3
IIFE
Сразу вызываемое выражение функции
Node.js
(function(name) {
console.log('hello', name)
})('bob')
Выход
hello bob
Go
package main import "fmt" func main() { func(name string) { fmt.Println("hello", name) }("bob") }
Выход
hello bob
Файлы
Примеры создания, открытия, записи, чтения, закрытия и удаления файлов.
Node.js
const fs = require('fs')
// create file fs.closeSync(fs.openSync('test.txt', 'w'))
// open file (returns file descriptor) const fd = fs.openSync('test.txt', 'r+')
let wbuf = Buffer.from('hello world.') let rbuf = Buffer.alloc(12) let off = 0 let len = 12 let pos = 0
// write file fs.writeSync(fd, wbuf, pos)
// read file fs.readSync(fd, rbuf, off, len, pos)
console.log(rbuf.toString())
// close file fs.closeSync(fd)
// delete file fs.unlinkSync('test.txt')
Выход
hello world.
Go
package main import ( "fmt" "os" "syscall" ) func main() { // create file file, err := os.Create("test.txt") if err != nil { panic(err) } // close file file.Close() // open file file, err = os.OpenFile("test.txt", os.O_RDWR, 0755) if err != nil { panic(err) } // file descriptor fd := file.Fd() // open file (using file descriptor) file = os.NewFile(fd, "test file") wbuf := []byte("hello world.") rbuf := make([]byte, 12) var off int64 // write file if _, err := file.WriteAt(wbuf, off); err != nil { panic(err) } // read file if _, err := file.ReadAt(rbuf, off); err != nil { panic(err) } fmt.Println(string(rbuf)) // close file (using file descriptor) if err := syscall.Close(int(fd)); err != nil { panic(err) } // delete file if err := os.Remove("test.txt"); err != nil { panic(err) } }
Выход
hello world.
JSON
Примеры того, как анализировать (демаршалировать) и структурировать (маршалировать) JSON.
Node.js
let jsonstr = '{"foo":"bar"}'
let parsed = JSON.parse(jsonstr) console.log(parsed)
jsonstr = JSON.stringify(parsed) console.log(jsonstr)
Выход
{ foo: 'bar' } {"foo":"bar"}
Go
package main import ( "encoding/json" "fmt" ) type T struct { Foo string `json:"foo"` } func main() { jsonstr := `{"foo":"bar"}` t := new(T) err := json.Unmarshal([]byte(jsonstr), t) if err != nil { panic(err) } fmt.Println(t) marshalled, err := json.Marshal(t) jsonstr = string(marshalled) fmt.Println(jsonstr) }
Выход
&{bar} {"foo":"bar"}
Большие числа
Примеры создания типов с большими числами из и в uint, string, hex и буферы.
Node.js
const BN = require('bn.js')
let bn = new BN(75) console.log(bn.toString(10))
bn = new BN('75') console.log(bn.toString(10))
bn = new BN(0x4b, 'hex') console.log(bn.toString(10))
bn = new BN('4b', 'hex') console.log(bn.toString(10))
bn = new BN(Buffer.from('4b', 'hex')) console.log(bn.toString(10)) console.log(bn.toNumber(10)) console.log(bn.toString('hex')) console.log(bn.toBuffer())
let bn2 = new BN(5) let isEqual = bn.cmp(bn2) == 0 console.log(isEqual)
bn2 = new BN('4b', 'hex') isEqual = bn.cmp(bn2) == 0 console.log(isEqual)
Выход
75 75 75 75 75 75 4b <Buffer 4b> false true
Go
package main import ( "encoding/hex" "fmt" "math/big" ) func main() { bn := new(big.Int) bn.SetUint64(75) fmt.Println(bn.String()) bn = new(big.Int) bn.SetString("75", 10) fmt.Println(bn.String()) bn = new(big.Int) bn.SetUint64(0x4b) fmt.Println(bn.String()) bn = new(big.Int) bn.SetString("4b", 16) fmt.Println(bn.String()) bn = new(big.Int) bn.SetBytes([]byte{0x4b}) fmt.Println(bn.String()) fmt.Println(bn.Uint64()) fmt.Println(hex.EncodeToString(bn.Bytes())) fmt.Println(bn.Bytes()) bn2 := big.NewInt(5) isEqual := bn.Cmp(bn2) == 0 fmt.Println(isEqual) bn2 = big.NewInt(75) isEqual = bn.Cmp(bn2) == 0 fmt.Println(isEqual) }
Выход
75 75 75 75 75 75 4b [75] false true
Обещания
Node.js
function asyncMethod(value) { return new Promise((resolve, reject) => { setTimeout(() => { resolve('resolved: ' + value) }, 1e3) }) }
function main() { asyncMethod('foo') .then(result => console.log(result)) .catch(err => console.error(err))
Promise.all([ asyncMethod('A'), asyncMethod('B'), asyncMethod('C') ]) .then(result => console.log(result)) .catch(err => console.error(err)) }
main()
Выход
resolved: foo [ 'resolved: A', 'resolved: B', 'resolved: C' ]
Go
(ближе всего использовать каналы)
package main import ( "fmt" "sync" "time" "github.com/prometheus/common/log" ) func asyncMethod(value string) chan interface{} { ch := make(chan interface{}, 1) go func() { time.Sleep(1 * time.Second) ch <- "resolved: " + value close(ch) }() return ch } func resolveAll(ch ...chan interface{}) chan interface{} { var wg sync.WaitGroup res := make([]string, len(ch)) resCh := make(chan interface{}, 1) go func() { for i, c := range ch { wg.Add(1) go func(j int, ifcCh chan interface{}) { ifc := <-ifcCh switch v := ifc.(type) { case error: resCh <- v case string: res[j] = v } wg.Done() }(i, c) } wg.Wait() resCh <- res close(resCh) }() return resCh } func main() { var wg sync.WaitGroup wg.Add(2) go func() { result := <-asyncMethod("foo") switch v := result.(type) { case string: fmt.Println(v) case error: log.Errorln(v) } wg.Done() }() go func() { result := <-resolveAll( asyncMethod("A"), asyncMethod("B"), asyncMethod("C"), ) switch v := result.(type) { case []string: fmt.Println(v) case error: log.Errorln(v) } wg.Done() }() wg.Wait() }
Выход
resolved: foo [resolved: A resolved: B resolved: C]
Асинхронный / ожидание
Node.js
function hello(name) { return new Promise((resolve, reject) => { setTimeout(() => { if (name === 'fail') { reject(new Error('failed')) } else { resolve('hello ' + name) } }, 1e3) }) }
async function main() { try { let output = await hello('bob') console.log(output)
output = await hello('fail') console.log(output) } catch(err) { console.log(err.message) } }
main()
Выход
hello bob failed
Go
(ближе всего использовать каналы)
package main import ( "errors" "fmt" "time" "github.com/prometheus/common/log" ) func hello(name string) chan interface{} { ch := make(chan interface{}, 1) go func() { time.Sleep(1 * time.Second) if name == "fail" { ch <- errors.New("failed") } else { ch <- "hello " + name } }() return ch } func main() { result := <-hello("bob") switch v := result.(type) { case string: fmt.Println(v) case error: log.Errorln(v) } result = <-hello("fail") switch v := result.(type) { case string: fmt.Println(v) case error: log.Errorln(v) } }
Выход
hello bob failed
Потоки
Примеры чтения и записи потоков
Node.js
const { Readable, Writable } = require('stream')
const inStream = new Readable()
inStream.push(Buffer.from('foo')) inStream.push(Buffer.from('bar')) inStream.push(null) // end stream inStream.pipe(process.stdout)
const outStream = new Writable({ write(chunk, encoding, callback) { console.log('received: ' + chunk.toString('utf8')) callback() } })
outStream.write(Buffer.from('abc')) outStream.write(Buffer.from('xyz')) outStream.end()
Выход
foobar received: abc received: xyz
Go
package main import ( "bufio" "bytes" "fmt" "io" "os" "runtime" ) func main() { inStream := new(bytes.Buffer) w := bufio.NewWriter(inStream) _, err := w.Write([]byte("foo")) if err != nil { panic(err) } _, err = w.Write([]byte("bar")) if err != nil { panic(err) } err = w.Flush() if err != nil { panic(err) } inStream.WriteTo(os.Stdout) fmt.Print("\n") outStream := new(bytes.Buffer) outStream.Write([]byte("abc\n")) outStream.Write([]byte("xyc\n")) piper, pipew := io.Pipe() go func() { sc := bufio.NewScanner(piper) for sc.Scan() { fmt.Println("received: " + sc.Text()) } if err := sc.Err(); err != nil { panic(err) } os.Exit(0) }() go func() { defer pipew.Close() io.Copy(pipew, outStream) }() defer runtime.Goexit() }
Выход
foobar received: abc received: xyc
Эмиттер событий
Node.js
const EventEmitter = require('events') class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter()
myEmitter.on('my-event', msg => { console.log(msg) })
myEmitter.on('my-other-event', msg => { console.log(msg) })
myEmitter.emit('my-event', 'hello world') myEmitter.emit('my-other-event', 'hello other world')
Выход
hello world hello other world
Go
(ближе всего использовать каналы)
package main import ( "fmt" ) type MyEmitter map[string]chan string func main() { myEmitter := MyEmitter{} myEmitter["my-event"] = make(chan string) myEmitter["my-other-event"] = make(chan string) go func() { for { select { case msg := <-myEmitter["my-event"]: fmt.Println(msg) case msg := <-myEmitter["my-other-event"]: fmt.Println(msg) } } }() myEmitter["my-event"] <- "hello world" myEmitter["my-other-event"] <- "hello other world" }
Выход
hello world hello other world
Ошибки
Node.js
const err1 = new Error('some error')
console.log(err1)
class FooError extends Error{ constructor(message) { super(message) this.name = 'FooError' this.message = message }
toString() { return this.message } }
const err2 = new FooError('my custom error')
console.log(err2)
Выход
Error: some error { FooError: my custom error }
Go
package main import ( "errors" "fmt" ) type FooError struct { s string } func (f *FooError) Error() string { return f.s } func NewFooError(s string) error { return &FooError{s} } func main() { err1 := errors.New("some error") fmt.Println(err1) err2 := NewFooError("my custom error") fmt.Println(err2) }
Выход
some error my custom error
Попробуй поймать
Node.js
function foo(fail) { if (fail) { throw Error('my error') } }
function main() { try { foo(true) } catch(err) { console.log(`caught error: ${err.message}`) } }
main()
Выход
caught error: my error
Go
package main import ( "errors" "fmt" ) func foo(fail bool) error { if fail { return errors.New("my error") } return nil } func main() { err := foo(true) if err != nil { fmt.Printf("caught error: %s\n", err.Error()) } }
Выход
caught error: my error
Исключения
Node.js
function foo() { throw Error('my exception') }
function main() { foo() }
process.on('uncaughtException', err => { console.log(`caught exception: ${err.message}`) process.exit(1) })
main()
Выход
caught exception: my exception
Go
package main import ( "fmt" ) func foo() { panic("my exception") } func main() { defer func() { if r := recover(); r != nil { fmt.Printf("caught exception: %s", r) } }() foo() }
Выход
caught exception: my exception
Регулярное выражение
Node.js
let input = 'foobar' let replaced = input.replace(/foo(.*)/i, 'qux$1') console.log(replaced)
let match = /o{2}/i.test(input) console.log(match)
input = '111-222-333' let matches = input.match(/([0-9]+)/gi) console.log(matches)
Выход
quxbar true [ '111', '222', '333' ]
Go
package main import ( "fmt" "regexp" ) func main() { input := "foobar" re := regexp.MustCompile(`(?i)foo(.*)`) replaced := re.ReplaceAllString(input, "qux$1") fmt.Println(replaced) re = regexp.MustCompile(`(?i)o{2}`) match := re.Match([]byte(input)) fmt.Println(match) input = "111-222-333" re = regexp.MustCompile(`(?i)([0-9]+)`) matches := re.FindAllString(input, -1) fmt.Println(matches) }
Выход
quxbar true [111 222 333]
Exec (синхронизация)
Node.js
const { execSync } = require('child_process') const output = execSync(`echo 'hello world'`) console.log(output.toString())
Выход
hello world
Go
package main import ( "fmt" "os/exec" ) func main() { output, err := exec.Command("echo", "hello world").Output() if err != nil { panic(err) } fmt.Println(string(output)) }
Выход
hello world
Exec (асинхронный)
Node.js
const { exec } = require('child_process') exec(`echo 'hello world'`, (error, stdout, stderr) => { if (error) { console.error(err) } if (stderr) { console.error(stderr) } if (stdout) { console.log(stdout) } })
Выход
hello world
Go
package main import ( "os" "os/exec" ) func main() { cmd := exec.Command("echo", "hello world") cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Run() }
Выход
hello world
TCP сервер
Node.js
const net = require('net')
function handler(socket) { socket.write('Received: ') socket.pipe(socket) }
const server = net.createServer(handler) server.listen(3000)
Выход
$ echo 'hello' | nc localhost 3000 Received: hello
Go
package main import ( "bufio" "net" ) func handler(conn net.Conn) { defer conn.Close() reader := bufio.NewReader(conn) for { message, err := reader.ReadString('\n') if err != nil { return } conn.Write([]byte("Received: ")) conn.Write([]byte(message)) } } func main() { listener, err := net.Listen("tcp", ":3000") if err != nil { panic(err) } defer listener.Close() for { conn, err := listener.Accept() if err != nil { panic(err) } go handler(conn) } }
Выход
$ echo 'hello' | nc localhost 3000 Received: hello
Сервер udp
Node.js
const dgram = require('dgram') const server = dgram.createSocket('udp4')
server.on('error', err => { console.error(err) server.close() })
server.on('message', (msg, rinfo) => { const data = msg.toString('utf8').trim() console.log(`received: ${data} from ${rinfo.address}:${rinfo.port}`) })
server.on('listening', () => { const address = server.address() console.log(`server listening ${address.address}:${address.port}`) })
server.bind(3000)
Выход
$ echo 'hello world' > /dev/udp/0.0.0.0/3000 server listening 0.0.0.0:3000 received: hello world from 127.0.0.1:51452
Go
package main import ( "fmt" "net" "strings" ) func main() { conn, err := net.ListenUDP("udp", &net.UDPAddr{ Port: 3000, IP: net.ParseIP("0.0.0.0"), }) if err != nil { panic(err) } defer conn.Close() fmt.Printf("server listening %s\n", conn.LocalAddr().String()) for { message := make([]byte, 20) rlen, remote, err := conn.ReadFromUDP(message[:]) if err != nil { panic(err) } data := strings.TrimSpace(string(message[:rlen])) fmt.Printf("received: %s from %s\n", data, remote) } }
Выход
$ echo 'hello world' > /dev/udp/0.0.0.0/3000 server listening [::]:3000 received: hello world from 127.0.0.1:50275
HTTP-сервер
Node.js
const http = require('http')
function handler(request, response) { response.writeHead(200, { 'Content-type':'text/plain' }) response.write('hello world') response.end() }
const server = http.createServer(handler) server.listen(8080)
Выход
$ curl http://localhost:8080 hello world
Go
package main import ( "net/http" ) func handler(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) w.Write([]byte("hello world")) } func main() { http.HandleFunc("/", handler) if err := http.ListenAndServe(":8080", nil); err != nil { panic(err) } }
Выход
$ curl http://localhost:8080 hello world
Разбор URL
Node.js
const url = require('url') const qs = require('querystring')
const urlstr = 'http://bob:[email protected]:8080/somepath?foo=bar'
const parsed = url.parse(urlstr) console.log(parsed.protocol) console.log(parsed.auth) console.log(parsed.port) console.log(parsed.hostname) console.log(parsed.pathname) console.log(qs.parse(parsed.search.substr(1)))
Выход
http: bob:secret 8080 sub.example.com /somepath { foo: 'bar' }
Go
package main import ( "fmt" "net/url" ) func main() { urlstr := "http://bob:[email protected]:8080/somepath?foo=bar" u, err := url.Parse(urlstr) if err != nil { panic(err) } fmt.Println(u.Scheme) fmt.Println(u.User) fmt.Println(u.Port()) fmt.Println(u.Hostname()) fmt.Println(u.Path) fmt.Println(u.Query()) }
Выход
http bob:secret 8080 sub.example.com /somepath map[foo:[bar]]
Gzip
Node.js
const zlib = require('zlib')
const data = Buffer.from('hello world', 'utf-8')
zlib.gzip(data, (err, compressed) => { if (err) { console.error(err) }
console.log(compressed)
zlib.unzip(compressed, (err, decompressed) => { if (err) { console.error(err) }
console.log(decompressed.toString()) }) })
Выход
<Buffer 1f 8b 08 00 00 00 00 00 00 13 cb 48 cd c9 c9 57 28 cf 2f ca 49 01 00 85 11 4a 0d 0b 00 00 00> hello world
Go
package main import ( "bytes" "compress/gzip" "fmt" ) func main() { data := []byte("hello world") compressed := new(bytes.Buffer) w := gzip.NewWriter(compressed) if _, err := w.Write(data); err != nil { panic(err) } if err := w.Close(); err != nil { panic(err) } fmt.Println(compressed.Bytes()) decompressed := new(bytes.Buffer) r, err := gzip.NewReader(compressed) if err != nil { panic(err) } _, err = decompressed.ReadFrom(r) if err != nil { panic(err) } fmt.Println(string(decompressed.Bytes())) }
Выход
[31 139 8 0 0 0 0 0 0 255 202 72 205 201 201 87 40 207 47 202 73 1 4 0 0 255 255 133 17 74 13 11 0 0 0] hello world
DNS
Пример поиска TXT
Node.js
const dns = require('dns')
dns.resolve4('google.com', (err, ips) => { if (err) { console.error(err) }
console.log(ips) })
dns.resolveMx('google.com', (err, mx) => { if (err) { console.error(err) }
console.log(mx) })
dns.resolveTxt('google.com', (err, txt) => { if (err) { console.error(err) }
console.log(txt) })
Выход
[ '172.217.11.78' ] [ { exchange: 'alt4.aspmx.l.google.com', priority: 50 }, { exchange: 'alt2.aspmx.l.google.com', priority: 30 }, { exchange: 'alt3.aspmx.l.google.com', priority: 40 }, { exchange: 'aspmx.l.google.com', priority: 10 }, { exchange: 'alt1.aspmx.l.google.com', priority: 20 } ] [ [ 'v=spf1 include:_spf.google.com ~all' ], [ 'docusign=05958488-4752-4ef2-95eb-aa7ba8a3bd0e' ], [ 'facebook-domain-verification=22rm551cu4k0ab0bxsw536tlds4h95' ], [ 'globalsign-smime-dv=CDYX+XFHUw2wml6/Gb8+59BsH31KzUr6c1l2BPvqKX8=' ] ]
Go
package main import ( "fmt" "net" ) func main() { ips, err := net.LookupIP("google.com") if err != nil { panic(err) } fmt.Println(ips) mx, err := net.LookupMX("google.com") if err != nil { panic(err) } fmt.Println(mx) txt, err := net.LookupTXT("google.com") if err != nil { panic(err) } fmt.Println(txt) }
Выход
[172.217.5.78 2607:f8b0:4007:80d::200e] [0xc0000ba2e0 0xc0000ba260 0xc0000ba2a0 0xc0000ba280 0xc0000ba300] [facebook-domain-verification=22rm551cu4k0ab0bxsw536tlds4h95 docusign=05958488-4752-4ef2-95eb-aa7ba8a3bd0e v=spf1 include:_spf.google.com ~all globalsign-smime-dv=CDYX+XFHUw2wml6/Gb8+59BsH31KzUr6c1l2BPvqKX8=]
Крипто
Node.js
const crypto = require('crypto')
const hash = crypto.createHash('sha256').update(Buffer.from('hello')).digest()
console.log(hash.toString('hex'))
Выход
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
Go
package main import ( "crypto/sha256" "encoding/hex" "fmt" ) func main() { hash := sha256.Sum256([]byte("hello")) fmt.Println(hex.EncodeToString(hash[:])) }
Выход
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
Env vars
Node.js
const key = process.env['API_KEY']
console.log(key)
Выход
$ API_KEY=foobar node examples/env_vars.js foobar
Go
package main import ( "fmt" "os" ) func main() { key := os.Getenv("API_KEY") fmt.Println(key) }
Выход
$ API_KEY=foobar go run examples/env_vars.go foobar
Cli args
Node.js
const args = process.argv.slice(2)
console.log(args)
Выход
$ node examples/cli_args.js foo bar qux [ 'foo', 'bar', 'qux' ]
Go
package main import ( "fmt" "os" ) func main() { args := os.Args[1:] fmt.Println(args) }
Выход
$ go run examples/cli_args.go foo bar qux [foo bar qux]
Cli флаги
Node.js
const yargs = require('yargs')
const { foo='default value', qux=false } = yargs.argv console.log('foo:', foo) console.log('qux:', qux)
Выход
$ node examples/cli_flags.js --foo='bar' --qux=true foo: bar qux: true
Go
package main import ( "flag" "fmt" ) func main() { var foo string flag.StringVar(&foo, "foo", "default value", "a string var") var qux bool flag.BoolVar(&qux, "qux", false, "a bool var") flag.Parse() fmt.Println("foo:", foo) fmt.Println("qux:", qux) }
Выход
$ go run examples/cli_flags.go -foo='bar' -qux=true foo: bar qux: true
Stdout
Node.js
process.stdout.write('hello world\n')
Выход
hello world
Go
package main import ( "fmt" "os" ) func main() { fmt.Fprint(os.Stdout, "hello world\n") }
Выход
hello world
Stderr
Node.js
process.stderr.write('hello error\n')
Выход
hello error
Go
package main import ( "fmt" "os" ) func main() { fmt.Fprint(os.Stderr, "hello error\n") }
Выход
hello error
Stdin
Node.js
const stdin = process.openStdin()
process.stdout.write('Enter name: ')
stdin.addListener('data', text => { const name = text.toString().trim() console.log('Your name is: ' + name)
stdin.pause() })
Выход
Enter name: bob Your name is: bob
Go
package main import ( "bufio" "fmt" "os" "strings" ) func main() { reader := bufio.NewReader(os.Stdin) fmt.Print("Enter name: ") text, err := reader.ReadString('\n') if err != nil { panic(err) } name := strings.TrimSpace(text) fmt.Printf("Your name is: %s\n", name) }
Выход
Enter name: bob Your name is: bob
Модули
Node.js
# initializing metadata and dependencies file (package.json) $ npm init # installing a module $ npm install moment --save # updating a module $ npm install moment@latest --save # removing a module $ npm uninstall moment --save # pruning modules (removing unused modules) $ npm prune # publishing a module $ npm publish// importing a module const moment = require('moment')
const now = moment().unix() console.log(now)
Выход
1546595748// exporting a module module.exports = { greet(name) { console.log(`hello ${name}`) } }
// importing exported module const greeter = require('./greeter')
greeter.greet('bob')
Выход
hello bob
Go
Настраивать
# enable Go modules support GO111MODULE=on # initializing dependencies file (go.mod) $ go mod init # installing a module $ go get github.com/go-shadow/moment # updating a module $ go get -u github.com/go-shadow/moment # removing a module $ rm -rf $GOPATH/pkg/mod/github.com/go-shadow/moment@v<tag>-<checksum>/ # pruning modules (removing unused modules from dependencies file) $ go mod tidy # download modules being used to local vendor directory (equivalent of downloading node_modules locally) $ go mod vendor # publishing a module: # Note: Go doesn't have an index of repositories like NPM. # Go modules are hosted as public git repositories. # To publish, simply push to the repository and tag releases. package main import ( "fmt" // importing a module "github.com/go-shadow/moment" ) func main() { now := moment.New().Now().Unix() fmt.Println(now) }
Выход
1546595748 package greeter import ( "fmt" ) // exporting a module (use a capitalized name to export function) func Greet(name string) { fmt.Printf("hello %s", name) } package main import ( // importing exported module greeter "github.com/miguelmota/golang-for-nodejs-developers/examples/greeter_go" ) func main() { greeter.Greet("bob") }
Выход
hello bob
Трассировки стека
Node.js
function foo() { throw new Error('failed') }
try { foo() } catch(err) { console.trace(err) }
Выход
Trace: Error: failed at foo (/Users/bob/examples/stack_trace.js:2:9) at Object.<anonymous> (/Users/bob/examples/stack_trace.js:6:3) at Module._compile (internal/modules/cjs/loader.js:688:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10) at Module.load (internal/modules/cjs/loader.js:598:32) at tryModuleLoad (internal/modules/cjs/loader.js:537:12) at Function.Module._load (internal/modules/cjs/loader.js:529:3) at Function.Module.runMain (internal/modules/cjs/loader.js:741:12) at startup (internal/bootstrap/node.js:285:19) at bootstrapNodeJSCore (internal/bootstrap/node.js:739:3) at Object.<anonymous> (/Users/bob/examples/stack_trace.js:8:11) at Module._compile (internal/modules/cjs/loader.js:688:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10) at Module.load (internal/modules/cjs/loader.js:598:32) at tryModuleLoad (internal/modules/cjs/loader.js:537:12) at Function.Module._load (internal/modules/cjs/loader.js:529:3) at Function.Module.runMain (internal/modules/cjs/loader.js:741:12) at startup (internal/bootstrap/node.js:285:19) at bootstrapNodeJSCore (internal/bootstrap/node.js:739:3)
Go
package main import ( "errors" "fmt" "runtime/debug" ) func foo() { panic(errors.New("failed")) } func main() { defer func() { if r := recover(); r != nil { fmt.Println(string(debug.Stack())) } }() foo() }
Выход
goroutine 1 [running]: runtime/debug.Stack(0xc000090eb8, 0x10a8400, 0xc00007e1c0) /Users/mota/.gvm/gos/go1.11/src/runtime/debug/stack.go:24 +0xa7 main.main.func1() /Users/bob/examples/stack_trace.go:16 +0x46 panic(0x10a8400, 0xc00007e1c0) /Users/mota/.gvm/gos/go1.11/src/runtime/panic.go:513 +0x1b9 main.foo(...) /Users/bob/examples/stack_trace.go:10 main.main() /Users/bob/examples/stack_trace.go:20 +0xa2
Базы данных
Пример создания таблицы, вставки строк и чтения строк из базы данных sqlite3
Node.js
const sqlite3 = require('sqlite3').verbose() const db = new sqlite3.Database('./sqlite3.db')
db.serialize(() => { db.run('CREATE TABLE persons (name TEXT)')
const stmt = db.prepare('INSERT INTO persons VALUES (?)') const names = ['alice', 'bob', 'charlie'] for (let i = 0; i < names.length; i++) { stmt.run(names[i]) }
stmt.finalize()
db.each('SELECT rowid AS id, name FROM persons', (err, row) => { if (err) { console.error(err) return }
console.log(row.id, row.name) }) })
db.close()
Выход
1 'alice' 2 'bob' 3 'charlie'
Go
package main import ( "database/sql" "fmt" _ "github.com/mattn/go-sqlite3" ) func main() { db, err := sql.Open("sqlite3", "./sqlite3.db") if err != nil { panic(err) } defer db.Close() _, err = db.Exec("CREATE TABLE persons (name TEXT)") if err != nil { panic(err) } tx, err := db.Begin() if err != nil { panic(err) } stmt, err := tx.Prepare("INSERT INTO persons VALUES (?)") if err != nil { panic(err) } defer stmt.Close() names := []string{"alice", "bob", "charlie"} for _, name := range names { _, err := stmt.Exec(name) if err != nil { panic(err) } } tx.Commit() rows, err := db.Query("SELECT rowid AS id, name FROM persons") if err != nil { panic(err) } defer rows.Close() for rows.Next() { var id int var name string err = rows.Scan(&id, &name) if err != nil { panic(err) } fmt.Println(id, name) } err = rows.Err() if err != nil { panic(err) } }
Выход
1 alice 2 bob 3 charlie
Тестирование
Node.js
const test = require('tape')
test(t => { const tt = [ {a:1, b:1, ret:2}, {a:2, b:3, ret:5}, {a:5, b:5, ret:10} ]
t.plan(tt.length)
tt.forEach(tt => { t.equal(sum(tt.a, tt.b), tt.ret) }) })
function sum(a, b) { return a + b }
Выход
$ node examples/example_test.js TAP version 13 # (anonymous) ok 1 should be equal ok 2 should be equal ok 3 should be equal 1..3 # tests 3 # pass 3 # ok
Go
package example import ( "fmt" "testing" ) func TestSum(t *testing.T) { for _, tt := range []struct { a int b int ret int }{ {1, 1, 2}, {2, 3, 5}, {5, 5, 10}, } { t.Run(fmt.Sprintf("(%v + %v)", tt.a, tt.b), func(t *testing.T) { ret := sum(tt.a, tt.b) if ret != tt.ret { t.Errorf("want %v, got %v", tt.ret, ret) } }) } } func sum(a, b int) int { return a + b }
Выход
$ go test -v examples/example_test.go === RUN TestSum === RUN TestSum/(1_+_1) === RUN TestSum/(2_+_3) === RUN TestSum/(5_+_5) --- PASS: TestSum (0.00s) --- PASS: TestSum/(1_+_1) (0.00s) --- PASS: TestSum/(2_+_3) (0.00s) --- PASS: TestSum/(5_+_5) (0.00s) PASS ok command-line-arguments 0.008s
Бенчмаркинг
Node.js
const Benchmark = require('benchmark')
const suite = new Benchmark.Suite suite.add('fib#recursion', () => { fibRec(10) }) .add('fib#loop', () => { fibLoop(10) }) .on('complete', () => { console.log(suite[0].toString()) console.log(suite[1].toString()) }) .run({ async: true })
function fibRec(n) { if (n <= 1) { return n }
return fibRec(n-1) + fibRec(n-2) }
function fibLoop(n) { let f = [0, 1] for (let i = 2; i <= n; i++) { f[i] = f[i-1] + f[i-2] } return f[n] }
Выход
$ node examples/benchmark_test.js fib#recursion x 1,343,074 ops/sec ±1.26% (84 runs sampled) fib#loop x 20,104,517 ops/sec ±3.78% (78 runs sampled)
Go
package example import ( "testing" ) func BenchmarkFibRec(b *testing.B) { for n := 0; n < b.N; n++ { fibRec(10) } } func BenchmarkFibLoop(b *testing.B) { for n := 0; n < b.N; n++ { fibLoop(10) } } func fibRec(n int) int { if n <= 1 { return n } return fibRec(n-1) + fibRec(n-2) } func fibLoop(n int) int { f := make([]int, n+1, n+2) if n < 2 { f = f[0:2] } f[0] = 0 f[1] = 1 for i := 2; i <= n; i++ { f[i] = f[i-1] + f[i-2] } return f[n] }
Выход
$ go test -v -bench=. -benchmem examples/benchmark_test.go goos: darwin goarch: amd64 BenchmarkFibRec-8 5000000 340 ns/op 0 B/op 0 allocs/op BenchmarkFibLoop-8 30000000 46.5 ns/op 96 B/op 1 allocs/op PASS ok command-line-arguments 3.502s
Документация
Node.js
/** * Creates a new Person. * @class * @example * const person = new Person('bob') */ class Person { /** * Create a person. * @param {string} [name] - The person's name. */ constructor(name) { this.name = name }
/** * Get the person's name. * @return {string} The person's name * @example * person.getName() */ getName() { return this.name }
/** * Set the person's name. * @param {string} name - The person's name. * @example * person.setName('bob') */ setName(name) { this.name = name } }
Go
person.go
package person import "fmt" // Person is the structure of a person type Person struct { name string } // NewPerson creates a new person. Takes in a name argument. func NewPerson(name string) *Person { return &Person{ name: name, } } // GetName returns the person's name func (p *Person) GetName() string { return p.name } // SetName sets the person's name func (p *Person) SetName(name string) string { return p.name }
person_test.go
// Example of creating a new Person. func ExampleNewPerson() { person := NewPerson("bob") _ = person } // Example of getting person's name. func ExamplePerson_GetName() { person := NewPerson("bob") fmt.Println(person.GetName()) // Output: bob } // Example of setting person's name. func ExamplePerson_SetName() { person := NewPerson("alice") person.SetName("bob") }
Вот и все
Теперь вы знаете достаточно, чтобы быть опасным. Продолжай учиться!