每日新闻

每日新闻

GoCN每日新闻资讯
有问必答

有问必答

Go相关的问题,技术相关的问题
文章分享

文章分享

技术文章分享,让知识传播给更多的人
招聘应聘

招聘应聘

为Gopher服务的招聘应聘平台

GoCN每日新闻(2020-01-02)

每日新闻dche423 回复了问题 • 2 人关注 • 2 个回复 • 10072 次浏览 • 2020-01-06 10:24 • 来自相关话题

GoCN每日新闻(2020-01-05)

回复

每日新闻罗发宣 发起了问题 • 1 人关注 • 0 个回复 • 1585 次浏览 • 2020-01-05 11:54 • 来自相关话题

Dig101: Go之for-range排坑指南

Golangnewbmiao 发表了文章 • 0 个评论 • 218 次浏览 • 2020-01-05 00:17 • 来自相关话题

好久没写了,打算今年做个Dig101系列,挖一挖技术背后的故事。Dig101: dig more, simplified more and know moregolang常用的 ...查看全部

好久没写了,打算今年做个Dig101系列,挖一挖技术背后的故事。

Dig101: dig more, simplified more and know more

golang常用的遍历方式,有两种: for 和 for-range。 而for-range使用中有些坑常会遇到,今天我们一起来捋一捋。

文章目录

  • 0x01 遍历取不到所有元素指针?
  • 0x02 遍历会停止么?
  • 0x03 对大数组这样遍历有啥问题?
  • 0x04 对大数组这样重置效率高么?
  • 0x05 对 map 遍历时删除元素能遍历到么?
  • 0x06 对 map 遍历时新增元素能遍历到么?
  • 0x07 这样遍历中起 goroutine 可以么?

可以移步 微信版地址 阅读全文

如何快速计算上传文件的 hash 值

回复

有问必答zwx490988 发起了问题 • 1 人关注 • 0 个回复 • 144 次浏览 • 2020-01-04 20:00 • 来自相关话题

GoCN每日新闻(2020-01-04)

回复

每日新闻cloudy 发起了问题 • 1 人关注 • 0 个回复 • 1318 次浏览 • 2020-01-04 18:33 • 来自相关话题

在 go websocket server 与 javascript websocket client 交互中使用 flatbuffers

文章分享tsingson 发表了文章 • 0 个评论 • 547 次浏览 • 2020-01-04 00:36 • 来自相关话题

> 代码在 [https://github.com/tsingson/fastws-example](https://github.com/ ...查看全部



> 代码在 [https://github.com/tsingson/fastws-example](https://github.com/tsingson/fastws-example)


## 0. 简要说明
为某个开源项目增加 websocket 对接, 写了这个示例

代码中 javascript 对 flatbuffers 的序列化/反序列化, 查了一天资料, 嗯哼, 最终完成了.
看代码吧.........

-----------
### 0.1 关于序列化/反序列化
序列化 serialized / 反序列化 un-serialized , 一般是指对像转成二进制序列( 或叫二进制数组), 以及逆向从二进制转成对像的过程, 一般用在几个地方
1. 网元之间传输. 比如 RESTfull 是在 HTTP 协议( HTML over TCP ) 上进行交互时使用 JSON 数据格式进行序列化与反序列化; 比如 gRPC 默认采用 protobuffers 在 HTTP2 传输上进行数据序列化与反序列化;
2. 对象数据持久化存储到文件系统, 以及从文件系统读取到对象时;
3. 异构开发SDK或API之间交互或共享数据, 比如 go语言调用底层 c++ 库........

### 0.2 关于 flatbuffers
flatbuffers 是 google 员工在开发游戏过程中, 仿 protobuffers 写的一个高性能序列化/反序列化库, 通过 IDL (接口描述语言) 定义, 通过 flatc 编译为多种语言的接口对象序列化/反序列化的强类型库, 支持 c++ / c / java / python / rust / js / typescript / go / swift.........

fastbuffers 的介绍, 参见 [于德志](https://halfrost.com/) 的文章 [https://halfrost.com/flatbuffers_schema/](https://halfrost.com/flatbuffers_schema/), 几篇文章写得很细致,精确,完整
> **PS: [于德志](https://halfrost.com/) 的技术专题介绍文章,语言简练易懂, 配图简单明了,非常值得一读**
>
>
> 说起来, 我的英文阅读能力还可以, 但不得不说, 访问 [于德志](https://halfrost.com/) 的 [https://halfrost.com/tag/protocol/ 协议相关专题文章](https://halfrost.com/tag/protocol/) 还是很愉悦轻松. 谢谢了!



flatbuffers 的特点, 个人见解:

1. flatbuffers 的序列化, 慢于 protobuffers ( 约是 protobuffers 的两倍耗时) , 与 JSON 相仿, 甚至有时慢于 json
2. flatbuffers 的反序列化, 约10倍快于 protobuffers, 当然也就快于 JSON 了
3. flatbuffers 在反序列化时, 是内在零拷贝, 序列化后的数据与内存中是一致的, 这让 flatbuffers 序列化后的二进制数据直接导入内存, 以及从内存中读取时都非常快

所以, 在一次序列化, 而多次反序列化的情况下, 以及对反序列化要求速度非常快的情况, 可以考虑选择 flatbuffers , 想想 google 员工为游戏而开发 flatbuffers 这一典型场景吧

### 0.3 我在哪里使用( 或计划使用 ) flatbuffers ?
在以下场景中, 我使用了( 或正在计划使用) flatbuffers:

1. Sub/Pub 订阅/发布的消息系统. 在某些 Sub/Pub 场景中, Pub 时序列化消息对象, 尤其是 flatbuffers 中的 union , 挺好用. ------------- 而在 Sub 订阅消费端, 尤其多端消费, 高效的反序列化, 可以减少最多达1/4, 平均1/5 左右时延 (注: 仅是个人应用场景的经验值, 供参考)
2. 内存缓存( 包括 session 会话数据) , 某些应用中的内存缓存需要持久化, 这些内存缓存通过并发保存到多个文件后, 在应用重启时从文件中重建缓存, 非常快
3. IM 即时通讯, 以及某些情况下的 gRPC, 这个与第一条类似. 参见我以前的文章 [GOIM的架构与定制](https://juejin.im/post/5cbb9e68e51d456e51614aab)------ 事实上, 这一篇文章, 正是为定制开发的 IM 而准备. --------- 至于 gRPC , 是的, gRPC 默认的 ptotobuffers 可以用 flatbuffers 更换, 我在几个商用项目中使用, 某商用项目中的 gRPC + flatbuffers 已经上线运行一年了.

### 0.4 flatbuffers 的重大改进

之前, flatbuffers 在序列化时代码很让人着急, 但2019年12月的一个改进, 让 flatbuffers 序列化时代码简化不少

```
flatc --gen-object-api ./*.fbs
```

以上参数的添加, 让 flatbuffers 序列化简单如下:

```
// --------------- 这是 fbs 文件中的 IDL
table LoginRequest{
msgID:int=1;
username:string;
password:string;
}

// -------------- 这是 flatc 编译后的 go 代码
type LoginRequestT struct {
MsgID int32
Username string
Password string
}

func LoginRequestPack(builder *flatbuffers.Builder, t *LoginRequestT) flatbuffers.UOffsetT {
if t == nil {
return 0
}
usernameOffset := builder.CreateString(t.Username)
passwordOffset := builder.CreateString(t.Password)
LoginRequestStart(builder)
LoginRequestAddMsgID(builder, t.MsgID)
LoginRequestAddUsername(builder, usernameOffset)
LoginRequestAddPassword(builder, passwordOffset)
return LoginRequestEnd(builder)
}

// ----------- 这是我做的简单封装
func (a *LoginRequestT) Byte() []byte {
b := flatbuffers.NewBuilder(0)
b.Finish(LoginRequestPack(b, a))
return b.FinishedBytes()
}


//---------------- 这里是序列化
l := &LoginRequestT{
MsgID: 1,
Username: "1",
Password: "1",
}

b := l.Byte() // ------------- 变量 b 是序列化后的二进制数组


```




## 1. 使用代码库

示例代码使用了以下开源库
* [fasthttp](http://github.com/valyala/fasthttp)
* [fasthttp router](https://github.com/fasthttp/router)
* [fastws ](https://github.com/fasthttp/fastws) ---- fasthttp 实现的 websocket 库
* [flatbuffers](https://github.com/google/flatbuffers) ---- flatbuffers 高效反序列化通用库, 用在 go语言/javascript
* [websockets/ws](https://github.com/websockets/ws) ---- javascript websocket 通用库

## 1. flatbuffers IDL 示例
xone.fbs 示例来自 [https://www.cnblogs.com/sevenstar/p/FlatBuffer.html](https://www.cnblogs.com/sevenstar/p/FlatBuffer.html), 感谢!!

```
namespace xone.genflat;

table LoginRequest{
msgID:int=1;
username:string;
password:string;
}

table LoginResponse{
msgID:int=2;
uid:string;
}

//root_type非必须。

//root_type LoginRequest;
//root_type LoginRespons
```

## 2. flatc 编译代码

生成 javascript

```
flatc -s --gen-mutable ./*.fbs
```



生成 golang

```
flatc --go --gen-object-api --gen-all --gen-compare --raw-binary ./*.fbs
```

## 3. 主要代码说明

```
./cmd/wsserver/main.go ----- websocket server
./cmd/wsclient/main.go ----- websocket client
./ws/... ------------------- websocket go code for websocket handler and websocket client
./jsclient/ws.js ---------- javascript client code , please check-out package.json for depends
```




## 4. javascript 序列化/反序列化

**请注意代码注释中的--------- 特别注意这一行**

```
// ------------ ./jsclient/index.js

const flatbuffers = require('./flatbuffers').flatbuffers;
const xone = require('./xone_generated').xone; //Generated by `flatc`.

//-------------------------------------------
// serialized
//-------------------------------------------
let b = new flatbuffers.Builder(1);
let username = b.createString("zlssssssssssssh");
let password = b.createString("xxxxxxxxxxxxxxxxxxx");
xone.genflat.LoginRequest.startLoginRequest(b);
xone.genflat.LoginRequest.addUsername(b, username);
xone.genflat.LoginRequest.addPassword(b, password);
xone.genflat.LoginRequest.addMsgID(b, 5);
let req = xone.genflat.LoginRequest.endLoginRequest(b);
b.finish(req); //创建结束时记得调用这个finish方法。


let uint8Array = b.asUint8Array(); // ------------- 特别注意这一行

console.log(uint8Array);
// console.log(b.dataBuffer() );
//-------------------------------------------
// un-serialized
//-------------------------------------------
let bb = new flatbuffers.ByteBuffer(uint8Array); //-------------- 特别注意这一行
let lgg = xone.genflat.LoginRequest.getRootAsLoginRequest(bb);


console.log("username: ", lgg.username());
console.log("password", lgg.password());
console.log("msgID: ", lgg.msgID());

```



## 5. golang 中对 flatbuffers 的序列化/反序列化

```

// ------ ./apis/genflat/model.go

func (a *LoginRequestT) Byte() []byte {
b := flatbuffers.NewBuilder(0)
b.Finish(LoginRequestPack(b, a))
return b.FinishedBytes()
}

func ByteLoginRequestT(b []byte) *LoginRequestT {
return GetRootAsLoginRequest(b, 0).UnPack()
}


// ------- ./apis/genflat/model_test.go

func TestLoginRequestT_Byte(t *testing.T) {
as := assert.New(t)
// serialized
l := &LoginRequestT{
MsgID: 1,
Username: "1",
Password: "1",
}

b := l.Byte()

// un-serialized
c := ByteLoginRequestT(b)
if l.MsgID > 0 {
fmt.Println(" id > ", c.MsgID, " u > ", c.Username, " pw > ", c.Password)
}

as.Equal(l.Password, c.Password)

}

```

## 6. websocket 代码
```

ws.onmessage = (event) => {
//-------------------------------------------------------------------
// read from websocket and un-serialized via flatbuffers
//--------------------------------------------------------------------
let aa = str2ab(event.data);
let bb = new flatbuffers.ByteBuffer(aa);
let lgg = xone.genflat.LoginRequest.getRootAsLoginRequest(bb);
let pw = lgg.password();

if (typeof pw === 'string') {
console.log("----------------------------------------------");

console.log("username: ", lgg.username());
console.log("password", lgg.password());
console.log("msgID: ", lgg.msgID());
} else {
console.log("=================================");
console.log(event.data);
}


// console.log(`Roundtrip time: ${Date.now() }` , ab2str(d ));

setTimeout(function timeout() {
//-------------------------------------------------------------------
// serialized via flatbuffers and send to websocket
//--------------------------------------------------------------------
let b = new flatbuffers.Builder(1);
let username = b.createString("zlssssssssssssh");
let password = b.createString("xxxxxxxxxxxxxxxxxxx");
xone.genflat.LoginRequest.startLoginRequest(b);
xone.genflat.LoginRequest.addUsername(b, username);
xone.genflat.LoginRequest.addPassword(b, password);
xone.genflat.LoginRequest.addMsgID(b, 5);
let req = xone.genflat.LoginRequest.endLoginRequest(b);
b.finish(req); //创建结束时记得调用这个finish方法。


let uint8Array = b.asUint8Array();

ws.send(uint8Array);
}, 500);
};

function str2ab(str) {
let array = new Uint8Array(str.length);
for (let i = 0; i < str.length; i++) {
array[i] = str.charCodeAt(i);
}
return array
}

```



## 6. 参考

* [https://github.com/google/flatbuffers/issues/3781](https://github.com/google/flatbuffers/issues/3781)



## 7. 其他

macOS 下从源码编译 flatc
```
git clone https://github.com/google/flatbuffers

cd github.com/google/flatbuffers

cmake -G "Xcode" -DCMAKE_BUILD_TYPE=Release

cmake --build . --target install

```

【蚂蚁金服】蚂蚁金服研发效能团队招人啦!

回复

招聘应聘vs小金刚 回复了问题 • 2 人关注 • 3 个回复 • 1050 次浏览 • 2020-01-03 19:13 • 来自相关话题

Go语言——sync.Map源码分析

回复

Golang有只黑白猫 发起了问题 • 1 人关注 • 0 个回复 • 127 次浏览 • 2020-01-03 16:10 • 来自相关话题

go语言错题及答案整理

Golang有只黑白猫 发表了文章 • 0 个评论 • 200 次浏览 • 2020-01-03 15:37 • 来自相关话题

点击这里,查看剩余错题及答案简介:&nb ...查看全部

点击这里,查看剩余错题及答案

简介: 本文即Go语言的那些坑三

不要对Go并发函数的执行时机做任何假设

请看下列的列子:

1import ( 2 "fmt" 3 "runtime" 4 "time" 5) 6func main(){ 7 names := []string{"lily", "yoyo", "cersei", "rose", "annei"} 8 for _, name := range names{ 9 go func(){10 fmt.Println(name)11 }()12 }13 runtime.GOMAXPROCS(1)14 runtime.Gosched()15}


请问输出什么?
答案:


1annei2annei3annei4annei5annei



为什么呢?是不是有点诧异?
输出的都是“annei”,而“annei”又是“names”的最后一个元素,那么也就是说程序打印出了最后一个元素的值,而name对于匿名函数来讲又是一个外部的值。因此,我们可以做一个推断:虽然每次循环都启用了一个协程,但是这些协程都是引用了外部的变量,当协程创建完毕,再执行打印动作的时候,name的值已经不知道变为啥了,因为主函数协程也在跑,大家并行,但是在此由于names数组长度太小,当协程创建完毕后,主函数循环早已结束,所以,打印出来的都是遍历的names最后的那一个元素“annei”。
如何证实以上的推断呢?
其实很简单,每次循环结束后,停顿一段时间,等待协程打印当前的name便可。


1import (2 "fmt"3 "runtime"4 "time"5)6func main(){7 names := []string{"lily", "yoyo", "cersei", "rose", "annei"}8 for _, name := range names{9 go func(){10 fmt.Println(name)11 }()12 time.Sleep(time.Second)13 }14 runtime.GOMAXPROCS(1)15 runtime.Gosched()16}


打印结果:

1lily2yoyo3cersei4rose5annei

以上我们得出一个结论,不要对“go函数”的执行时机做任何的假设,除非你确实能做出让这种假设成为绝对事实的保证。
**假设T类型的方法上接收器既有T类型的,又有_T指针类型的,那么就不可以在不能寻址的T值上调用_T接收器的方法**

请看代码,试问能正常编译通过吗?


1import ( 2 "fmt" 3) 4type Lili struct{ 5 Name string 6} 7func (Lili *Lili) fmtPointer(){ 8 fmt.Println("poniter") 9}10func (Lili Lili) fmtReference(){11 fmt.Println("reference")12}13func main(){14 li := Lili{}15 li.fmtPointer()16}


答案:

关键字 Go语言 程序员 开发者

Golang 新手教程:入门速成指南

Golang有只黑白猫 发表了文章 • 0 个评论 • 196 次浏览 • 2020-01-03 15:35 • 来自相关话题

点击这里,查看剩余 ...查看全部

点击这里,查看剩余数据类型、数组、流程控制等重要内容

简介: 在许多语言中,有许多方法可以解决某些给定的问题。因此 程序员可以花很多时间思考解决问题的最佳方法。 然而,Go 却是只有一种正确的方法来解决问题的语言。 这节省了开发人员的时间,并使大型代码库易于维护。 Go 中没有地图和过滤器等 “富有表现力” 的功能。

image.png
让我们从 Go(或 Golang)的一个小介绍开始。 Go 由 Google 工程师 Robert Griesemer,Rob Pike 和 Ken Thompson 设计。 它是一种静态类型的编译语言。 第一个版本于 2012 年 3 月作为开源发布。

“Go 是一种开源编程语言,可以轻松构建的简单,可靠,高效的软件”。 --- 关于 go

在许多语言中,有许多方法可以解决某些给定的问题。因此 程序员可以花很多时间思考解决问题的最佳方法。
然而,Go 却是只有一种正确的方法来解决问题的语言。
这节省了开发人员的时间,并使大型代码库易于维护。 Go 中没有地图和过滤器等 “富有表现力” 的功能。

“如果你有增加表现力的功能,通常会增加费用” --- Rob Pike

入门

Go 是由包组成的。 main 包告诉 Go 编译器该程序可以被编译成可执行文件,而不是一个共享的库。它是应用程序的入口。main 包被定义为如下格式:

package main

接下来,让我们通过在 Go 工作区中创建一个文件 main.go 来编写一个简单的 hello world 示例。

go的工作区

Go 中的工作空间由环境变量「GOPATH」定义。你写的任何代码都将写在工作区内。Go 将搜索 GOPATH 目录中的任何包,或者在安装 Go 时默认设置的 GOROOT 目录。 GOROOT 是安装 go 的路径。

将 GOPATH 设置为你想要的目录。 现在,让我们将它添加到文件夹〜/ workspace 中。

#写入 env
export GOPATH=~/workspace

#cd 到工作区目录\
cd ~/workspace

使用我们刚刚创建的工作空间文件夹中的以下代码创建文件 main.go。

Hello World!

package main

import (
"fmt"
)

func main(){
fmt.Println("Hello World!")
}

在上面的 demo 中, fmt 是 Go 中的内置包,它实现了格式化 I / O 的功能。
在 Go 中我们导入一个包使用 import 关键字func main 是代码执行的入口。Println 是 fmt 包中的一个函数,它为我们打印 “hello world”。
让我们看一下运行这个文件。 我们可以通过两种方式运行 Go 命令。 我们知道,Go 是一种编译语言,所以我们首先需要在执行之前编译它。

> go build main.go

这会创建一个二进制可执行文件 main,现在我们可以运行它:

> ./main
# Hello World!

还有另一种更简单的方法来运行程序。 go run 命令有助于抽象编译步骤。 您只需运行以下命令即可执行该程序。

go run main.go
# Hello World!

您可以使用 https://play.golang.org 来运行本文提到的代码。

变量

变量在 Go 语言中是一个很明确的定义。 Go 是一种静态类型的语言。这意味着在声明变量时我们就需要明确变量的类型。一般一个变量的定义如下:

var a int

上面的实例中,我们定义了一个 int 类型的变量 a ,默认会被赋值成 0 。使用以下语法可以初始化改变变量的值:

var a = 1

这里我们没有制定变量 a 的类型,在我们给它初始化为 1 时,它就自动被定义成了 int 类型的变量。
我们也可以使用一种更简短的语法来定义它:

message := "hello world"

我们也可以在同一行声明多个同类型变量:

var b, c int = 2, 3

数据类型


关键字:存储 JSON JavaScript 程序员 编译器 Go API 定位技术 数据格式

Go语言必备技能——加快你的工作效率

Go开源项目有只黑白猫 发表了文章 • 0 个评论 • 246 次浏览 • 2020-01-03 15:31 • 来自相关话题

点击这里,查看 ...查看全部

点击这里,查看集合,Playground链接,依赖包管理等更多内容

一句话技巧

把你面向对象的大脑扔到家里吧,去拥抱接口。
学习如何使用Go的方式做事,不要把别的的编程风格强行用在Go里面。
多用接口总比少用好。
拥抱这种简洁、并行、工整的语言。
阅读官网golang.org上所有的文档,真是棒呆了。
别忘了用gofmt。
多读源代码。
学习工具和组件,然后创造你自己的!码代码和学代码一样对成功必不可少。
学而不思则罔,思而不学则殆。《论语》

引入package的多种方式

有几种非常规方式来引入包(package)。接下来我会使用fmt来作为例子:

import format "fmt" - 为fmt创造一个别名。把代码中所有使用到fmt的内容用format.代替fmt.
import . "fmt" - 允许包内的内容不加fmt前缀而被被直接引用
import _ "fmt" - 阻止编译器为引入fmt却不使用里面的内容做引发的警告,执行package中的初始化函数。提醒一句,在这种情况下fmt是不可调用的
看这篇博客来了解更多细节。

Goimports
命令goimports可以更新您的Go导入行,添加缺少的行,并删除未引用的引导行。

它拥有和gofmt(插入式替换)相同的能力,但是goimports额外增加了修复imports的功能。

组织
Go是一种相对来说易学习的编程语言,但对于开发者来说,起初接触这门语言最困难的事情就是如何组织代码。scaffolding是人们喜欢Rails的原因之一,它可以给新晋的开发者清晰的方向,让他们明白在哪里插入代码,应该遵循怎样的编程风格。

作为扩展,Go使用go fmt这样的工具来提供开发者相同的功能。同样地,Go的编译器非常严格,它不会去编译没有使用的变量,或者没有使用的import声明。

自定义构造函数
我经常听到别人问,“我什么时候应该使用像NewJob这样的自定义构造函数?”,我的回答是“大多数情形下你没必要这么做”。然而,当你需要在初始化的时候就设置值,且你有一些默认值的时候,这就最好使用一个构造函数。在这个例子中,构造函数就比较有意义了,因此我们用如下的代码可以构建一个默认的logger:

关键字:javaScript 编译器 测试技术 Go 持续交付 C语言 开发者 Ruby

Go 语言的 10 个实用技巧

Go开源项目有只黑白猫 发表了文章 • 0 个评论 • 194 次浏览 • 2020-01-03 15:02 • 来自相关话题

点击这里,查看剩余7项实用技巧等更多重要内容 ...查看全部

点击这里,查看剩余7项实用技巧等更多重要内容

简介: Go语言实战学习小技巧

使用单一的 GOPATH
多个 GOPATH 的情况并不具有弹性。GOPATH 本身就是高度自我完备的(通过导入路径)。有多个 GOPATH 会导致某些副作用,例如可能使用了给定的库的不同的版本。你可能在某个地方升级了它,但是其他地方却没有升级。而且,我还没遇到过任何一个需要使用多个 GOPATH 的情况。所以只使用单一的 GOPATH,这会提升你 Go 的开发进度。

许多人不同意这一观点,接下来我会做一些澄清。像 etcd 或camlistore 这样的大项目使用了像 godep 这样的工具,将所有依赖保存到某个目录中。也就是说,这些项目自身有一个单一的 GOPATH。它们只能在这个目录里找到对应的版本。除非你的项目很大并且极为重要,否则不要为每个项目使用不同的 GOPATH。如果你认为项目需要一个自己的 GOPATH 目录,那么就创建它,否则不要尝试使用多个 GOPATH。它只会拖慢你的进度。

将 for-select 封装到函数中
如果在某个条件下,你需要从 for-select 中退出,就需要使用标签。例如:

func main() {

L:
for {
select {
case <-time.After(time.Second):
fmt.Println(“hello”)
default:
break L
}
}

fmt.Println(“ending”)
}
如你所见,需要联合break使用标签。这有其用途,不过我不喜欢。这个例子中的 for 循环看起来很小,但是通常它们会更大,而判断break的条件也更为冗长。

如果需要退出循环,我会将 for-select 封装到函数中:

`func main() {
foo()
fmt.Println(“ending”)
}

func foo() {
for {
select {
case <-time.After(time.Second):
fmt.Println(“hello”)
default:
return
}
}
}

你还可以返回一个错误(或任何其他值),也是同样漂亮的,只需要:

// 阻塞
if err := foo(); err != nil {
// 处理 err
}`

在初始化结构体时使用带有标签的语法

关键字:JavaScript 安全 数据库连接 测试技术 Go 数据库 Windows

Go语言错题及答案整理

回复

文章分享有只黑白猫 发起了问题 • 1 人关注 • 0 个回复 • 138 次浏览 • 2020-01-03 14:55 • 来自相关话题

GoCN每日新闻(2020-01-03)

回复

每日新闻samurai 发起了问题 • 1 人关注 • 0 个回复 • 1204 次浏览 • 2020-01-03 11:30 • 来自相关话题

Go 开发者进阶周刊(Jan week 1)

进阶周刊dyq 发表了文章 • 0 个评论 • 1171 次浏览 • 2020-01-02 22:42 • 来自相关话题

语言学习(Golang 编程知识与技巧)1. ...查看全部

语言学习(Golang 编程知识与技巧)

1.Golang 实现依赖注入

依赖注入是软件工程中经常使用到的一种技术,它提供了一种控制反转的机制,把控制权利交给了调用方。调用方来决定使用哪些参数,哪些对象来进行具体的业务逻辑。

它有几个好处:
1 它让调用方更灵活。
2 大量减少定义类型的代码量
3 增加代码的可用性,因为调用方只需要关注它需要的参数,不需要顾及它不需要的参数了。

2.理解 Golang 中函数调用的原理

函数是 Go 语言中的一等公民,理解和掌握函数的调用过程是深入学习 Golang 时无法跳过的步骤,这里会介绍 Go 语言中函数调用的过程和实现原理并与 C 语言中函数执行的过程进行对比,同时对参数传递的原理进行剖析,让读者能够清楚地知道 Go 在函数的执行过程中究竟都做了哪些工作。

3.Go 中 Linux管道

管道是Unix哲学的基石,它允许通过组合仅做一件事情的程序来处理更复杂的问题。

文中将实现一个可以在Unix管道中使用的简单Golang程序,使用的所有代码都在github.com/napicella/go-linux-pipes上。

4.图解Go里面的sync.Map了解编程语言核心实现源码

在大多数语言中原始map都不是一个线程安全的数据结构,那如果要在多个线程或者goroutine中对线程进行更改就需要加锁,除了加1个大锁,不同的语言还有不同的优化方式, 像在java和go这种语言其实都采用的是链表法来进行map的实现,本文也主要分析这种场景。

5.【译】Go 语言实践:编写可维护的程序的建议

本文为 Heptio 资深工程师、著名 Go 语言专家 David Cheney 关于 Go 语言实践的英文分享。

6.Go 系列教程

Go是一种编程语言,旨在快速编译,简化编程和在生产中高效执行。本教程将指导您在Ubuntu 18.04上通过命令行使用Go安装和配置编程工作区。

7. Go modules:最小版本选择

每个依赖管理解决方案都必须解决选择依赖项版本的问题。当前存在的许多版本选择算法都试图识别任何依赖项的“最新最大(latest greatest)”版本。如果您认为语义版本控制(sematic versioning)将被正确应用并且这种社会契约得到遵守,那么这是有道理的。在这样的情况下,依赖项的“最新最大”版本应该是最稳定和安全的版本,并且应与较早版本具有向后兼容性。至少在相同的主版本(major verion)依赖树中是如此。

Go决定采用其他方法,Russ Cox花费了大量时间和精力撰写文章演讲探讨Go团队的版本选择方法,即最小版本选择或MVS(Minimal Version Selection)。从本质上讲,Go团队相信MVS为Go程序实现痴线持久的和可重复的构建提供了最佳的方案。建议大家阅读这篇文章以了解Go团队为什么相信这一点。

在本文中,作者将尽最大努力解释MVS语义,展示一个实际的Go语言示例,并实际使用MVS算法。

8.如何正确的开始用 Go 编程

本文会演示简单的Go软件包的开发过程,并介绍了go命令行工具,这是我们获取,构建和安装Go软件包和命令的标准方法。

go工具要求你以特定方式组织代码,文中会介绍Go安装启动和运行的最简单方法。

9. Golang内存分配

Go语言内置运行时(就是runtime),不同于传统的内存分配方式,go为自主管理,最开始是基于tcmalloc架构,后面逐步迭新。自主管理可实现更好的内存使用模式,如内存池、预分配等,从而避免了系统调用所带来的性能问题。

 

工程实践(Go的项目应用实践)

1.使用 Go 优化我们的接口

整体介绍了下当接口耗时较长的时候的一般处理方案。

2.为什么 MongoDB 使用 B 树

MySQL 和 MongoDB 两种不同类型的数据库使用了相似却不同的数据结构,为什么 MySQL 选择使用 B+ 树而 MongoDB 使用 B 树呢?

3.利用 CPU cache 特性优化Go程序

如下Go语言伪代码,开启两个协程,分别对一个结构体变量中的两个相邻的数据成员进行n次原子自增操作,当打开_ [56]byte这个看似多余的代码后,程序运行速度加快了一倍!你知道是为什么吗?

4.清晰架构(Clean Architecture)的Go微服务: 设计原则

作者最近写了一个Go微服务应用程序,这个程序的设计来自三个灵感:

5. XSS简介以及如何保护你的客户(Go版本)

6.Go依赖注入工具 wire 与 dig 对比

7.我们为什么用GO语言来做区块链? 

在区块链公链的开发圈子里,我们找到了一些流行的编程语言,有C++、Golang、Python和最近新起的Rust等等。老一代的公链,比如Bitcoin,Litcoin一般使用C/C++较多(我们看看那个时间,当时Go还没起来呢),新一代的公链比如以太坊,联盟链翘楚超级账本,开始较多使用Go语言,当然我们看到Rust的发展势头也很猛,近两年的很多公链比如波卡,Grin都开始采用Rust语言开发了。

8.Golang 错误处理最佳实践

 

生态拓展(云原生等 Go 生态体系)

1.微服务架构的 10个 最佳实践

微服务架构是将软件系统分解为自主模块,自主模块可以独立部署,通过轻量级的、与语言无关的方式进行通信,共同实现业务目标。

2.GOMAXPROCS 与容器的相处之道

众所周知,GOMAXPROCS 是 Golang 提供的非常重要的一个环境变量设定。通过设定 GOMAXPROCS,用户可以调整 Runtime Scheduler 中 Processor(简称P)的数量。由于每个系统线程,必须要绑定 P 才能真正地进行执行。所以 P 的数量会很大程度上影响 Golang Runtime 的并发表现。GOMAXPROCS 在目前版本(1.12)的默认值是 CPU 核数,而以 Docker 为代表的容器虚拟化技术,会通过 cgroup 等技术对 CPU 资源进行隔离。以 Kubernetes 为代表的基于容器虚拟化实现的资源管理系统,也支持这样的特性。这类技术对 CPU 的隔离限制,是否能够影响到 Golang 中的 GOMAXPROCS,进而影响到 Golang Runtime 的并发表现呢?这是一个值得探索的话题,本文从 Docker 和 Kubernetes 对 CPU 资源的限制出发,利用实验的方式验证了这一问题,并且给出了一些个人看法。

3. 使用多阶段构建的精益Golang Docker镜像

4. 您需要了解的有关Kubernetes服务质量(QoS)

服务质量(QoS)类是Kubernetes的概念,它确定Pod的调度和驱逐优先级。 Kubernetes调度程序使用QoS类来做出有关将Pod调度到节点上的决策。 


开源项目(社区新涌现的开源成果)

Gos:GO MODULE解决方案

tamago为 ARM Socs 打造裸金属框架

sqlstatsPrometheus 准备的 sql.DBStates 收集

go-term-markdown:Go Markdown终端渲染库

sqlite:无需CGO的Go SQLite连接库  


彩蛋(活动与招聘)

01.04 Gopher Meetup Plus 深圳站活动 报名

  • ž   Asta——Go在工业领域的应用实践
  • ž   腾讯——Go性能优化之路
  • ž   广发证券——Go与极限性能实践
  • ž   OPPO——云平台存储系统架构设计与容器化实践
  • ž   平安科技——从面试题目到Golang汇编
  • ž   腾讯——如何向Go官方提交代码
  • ž   华为云——KubeEdge:云原生边缘计算平台的Golang实践

北京】【商汤科技招聘】Golang开发实习生 详情

【杭州】【蚂蚁金服】蚂蚁金服研发效能团队招人啦!详情

【上海】【趣头条旗下米读小说】资深后端研发/架构师 详情

【武汉】【奇虎360】招聘资深golang工程师 详情