SlideShare ist ein Scribd-Unternehmen logo
1 von 63
INTRODUCTION
TO
GOLANG
傅理
@TAP4FUN
历史
2007年 : 在google秘密启动go语言研发
2009年 : 官方宣布go语言项目的存在,开始用于部分google生产系
统
2012年 : 第一个1.0正式版发布
当前版本: 1.1.2
https://code.google.com/p/go/downloads/list
主要目标
并行计算
• 利用好Google内部百万台服务器,摩尔定律在多核上的继续生
效,使得世界迫切需要一门并行的语言。(erlang前两年的突然
流行,就是一个写照,但由于其过高的门槛(函数式编程),
在工程上并没有大面积的普及。)
解决C++编译速度问题
• 软件规模庞大,C++编译速度不可忍受,google内部大型项目
编译时间通常以天计算。
主要目标
Bruce Eckel 表示:
C++的复杂性(新C++更复杂),对于生产效率的影响,已经不
再合理了。程序员为了使用好C++, 需要跳过很多坑,是完全说不
通的,只是浪费你的时间和精力。现在,go对C++想要解决的那类
问题,做的更合理。
( Bruce Eckel: The complexity of C++ (even more complexity has been added
in the new C++), and the resulting impact on productivity, is no longer justified. All
the hoops that the C++ programmer had to jump through in order to use a C-
compatible language make no sense anymore -- they‗re just a waste of time and
effort. Now, Go makes much more sense for the class of problems that C++ was
originally intended to solve.)
AUTHORS
Go语言的所有开发者,总共有400多位。
来源:
http://golang.org/CONTRIBUTORS
其中有几位非常著名的人物。
AUTHORS
Robert Griesemer
Chrome浏览器的Javascript engine (V8) 作者,目前是全世界最快的
浏览器,参与过Java Hotspot VM研发.
AUTHORS
Rob Pike(1956~)
Plan9,Inferno 操作系统设计者, UTF-8创造者,在贝尔实验室工作。
―设备即文件‖就由这位大神提出,深刻的影响了UNIX设计。
AUTHORS
Ken Thompson(1943~)
Thompson和Ritchie在1971年共同发明了C语言。1973年
Thompson和Ritchie用C语言重写了UNIX,从此开创了UNIX时
代。 1983年的图灵奖获得者。
谁说超过30就不能写程序来着?
GOLANG
FEATURES
GO语言基本特征
基本特征
1. 一门系统编程语言
2. 开源(社区性)
3. 语法接近C语言(因为Ken的一脉相承)
4. 多平台支持 (Linux,Mac,Windows,BSD)
5. 静态语言,需要编译
6. 自动内存管理,垃圾回收(GC)
官方主页: http://golang.org
官方教程: http://tour.golang.org/ (极其重要,一定要拿100分!)
关键字
共25个关键词(ANSI C语言32 个,C++ 63个,Lua 20个,Java50个)
GO语言在关键词使用上是非常吝啬的。
Keep it simple, make it general, and make it intelligible.
--- Douglas McIlroy
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var
运算符
优先级 运算符
最高 * / % << >> &
&^
+-|^
== != < <= > >=
<-
&&
最低 ||
1. 省掉了~取反符,单目^表示取反,
2. 调整了 & 和 == 的优先级
(在C语言中 位运算的 & ^ | 竟比比较运算
< == 优先级还低这一点不科学,因为合乎情
理的写法是 a&1 == 0,但实际上必须写
(a&1) == 0。不过,这一问题的来源是历史
遗留,在 C89 之前,K&R C 并没有逻辑运算
符 && 和 ||,而是使用 & 和 | 来表示这一
意义,按使用的上下文区分意义。后来 C89
标准化,虽然增加了语义更合理的 && 和 ||,
但大概是为了兼容旧代码,也没有把这个优先
级改过来,结果就将错就错了。)
int main(void) {
int a = 2;
printf("%dn", a&1==0);
printf("%dn", (a&1)==0);
} (奇偶性)
int8 int16 int32 int64
uint8 uint16 uint32 uint64
float32 float64 string rune
complex64 complex128 ...
基础数据类型
基本数据类型完全符合C99标准<stdint.h>, 即确定长度的严格数
据类型, 如:
UTF-8字符
原生支持
(想想Rob Pike)
go源码亦为utf8
rune [ruːn]: n. 诗歌;古代北欧文字;神秘的记号
LONG, LONG LONG ? NO!
复合数据类型
Array 类似于C的固定长度数组(不常用)
Slice 可变长度数组,切片(最常用,类似stl vector),最终
指向一个Array
Map 映射表(key->value), Hash表
Struct 结构体,和C语言结构体意义相同
与JSON的对比
JSON规范中,定义了:
object = { string:value } 无穷“名称/值”对
array = [value,value,value] 无穷 有序集合
value = string, number…array… 基本类型
并可形成一种无穷嵌套关系:
object:{ object:{ object:{object:,...}, ...},...}
在go语言中,go的数据结构和json是同构的。从go语言的数据结构导入导出
json格式,只需要一行代码。(想到robert了么,还想到了什么?)
map[string]interface{} --> 无穷键值对
slice interface{} --> 无穷有序集合
在GO构造一个
LOOP试试
编译过程回顾(C语言)
假设:
有C1, C2, C2三个C文件,
都引用了―common.h‖
那么:
common.h需要被编译3次
在google曾经的某个项目中,一个.h文件,被编译了30多万次,不
必要的重复include导致编译速度急剧下降。(想想.pch, .gch的作
用). C++诞生过若干解决编译速度的设计,例如: Pimpl技术
GO提高编译速度的途径
Go语言强制规定:如果有引用后没有使用到的包,编译时报错。
这样保证了,只有具有真正的依赖关系的
编译链条被建立。
保证:
一个文件,最多只被编译一次
一次都没有引用到的,决不编译。
一个上万行的工程,go只需要几秒编译。
循环依赖
编译过程中的循环依赖是不被允许的,即
引用关系不能形成环!(黑话叫DAG,有向无
环图)
一个编译的例子
问题:
假如存在如右图的编译依赖关系,在一个双核
的CPU上怎么编译最快。
答案:
第一步:D
第二步:C,F
第三步:B,E
第四步: A
即通过依赖关系寻找到最远的一个节点,
并回溯各条路径。
(思考:如果是4核CPU该如何编译?)
相比其他语言
Go语言如是说:
编译比我快的,运行速度没我
快;运行速度比我快的,编译没我
快!
系统编程
Go语言重新封装了所有的系统调用,具有和C语言相同的对系统的操
作能力。(PS: thompson和pike都设计过OS)
25 TEXT runtime·open(SB),7,$0
26 MOVL $5, AX // syscall-5 - open
27 MOVL 4(SP), BX // pathname
28 MOVL 8(SP), CX // flag
29 MOVL 12(SP), DX // mode
30 CALL *runtime·_vdso(SB)
31 RET
int open(const char *pathname, int flags, mode_t mode);
引自:
http://golang.org/src/pkg/runtime/sys_linux_386.s
系统调用是内核所
能提供的全部功能
系统编程举例
Go语言能直接处理UNIX Signal,因此,可以通过信号实现一些有用的功能,例
如通过注册一个信号接收通道:
signal.Notify(ch, syscall.SIGHUP, syscall.SIGQUIT)
然后通过kill给进程发消息:
$kill –HUP PID
就可以执行诸如重新加载游戏数值,或者在收到QUIT消息的时候,执行一些数据
库持久化操作,优雅的退出(shutdown gracefully)。
更多的系统调用,见:
http://golang.org/pkg/syscall/
C++
PERSPECTIVE
OF GOLANG
从C++的角度来看GOLANG
名字空间和类 VS. 目录
1. 一个目录中的所有文件同属一个namespace (朴素思想来源?)
2. 同一目录、不同文件的变量,函数,互相可见,因此也类似于
Class
3. 小写字母开头的为private函数/变量
func test() var a  对其他目录不可见
4. 大写字母开头的为public函数/变量
func Test() var A  对其他目录可见
对象方法 VS. 接收函数
func (slice ByteSlice) Append(data []byte) []byte {
}
Go语言没有类的概念,比较接近的是结构体。
可以定义一个结构体,并给这个结构体定义一个接收函数,然后通过
―对象 点 方法‖的形式去调用一个struct 方法(函数指针?)例如
aSlice.Append(…)
但没有完整意义上的对象方法, 也没有隐含的this指针.
继承 VS. 嵌入
type A struct {
a int
}
type B struct {
b int
}
嵌入:
type AB struct {
A
B
}
可以将两个struct内的字段合并到一
个新的结构体。
构造函数 VS. INIT()
结构体没有构造函数,但一个目录/一个文件中可以有若干个init
函数,init函数是全局的, 程序启动一次性的执行. (在main函数执
行之前)
var names = map[string]int
func init() {
names = make(map[string]int)
}
类似于C++在程序启动的时候,全局object执行构造函数。
INTERFACE VS.
VTABLE
Go语言提供了interface类型,表示一个接口方法集。仸何一个数据
类型,都实现了空方法集 interface{},类似于 void *
go语言支持reflect, 即仸何数据都有对应的元数据,包含其类型的
详细信息。如同 dynamic_cast 需要检查的vtable,也包含了类型
信息(RTTI),typeid()函数。
可以通过 type assertion 方法执行转换。
value.(typeName)  type assertion
类似于C++中
dynamic_cast<typeName*>(ptr)
EXCEPTIONS VS.
PANIC/RECOVER
panic()触发异常, recover()捕获异常
通过go语言的closure(闭包)
可以获得和C++ try -> catch() 相同效果
因为go语言支持多值返回,大部分的错误都在返回值中处理
了,因此panic确实应该在真正的―异常‖中触发。
“千万不要把错误当异常”
a, b = b, a
DEFER OR FINALLY
defer 的作用类似于finally:
C++代码
try {
fd = fopen(―xxx‖)
}
catch(…) {}
finally() {
close(fd)
}
等价于:
f, err := os.Open(―xxx‖)
If err!= nil …..
defer f.close()
HOW DOES A GO
PROJECT LOOK
LIKE?
工程组织
RULE #1 用树状目录的方式
组织工程
一个目录下所有.go文件共同构成一个功能模块, 为一个目的服务.
Example:
/src/agent/
agent.go buffer.go proxy.go session_work.go
RULE #2:
用 模块 + 接口 的方式去构建系统
而不是OOP的方式
CONCURRENT
PROGRAMMING
IN GOLANG
GOLANG并发编程
THREADS回顾
进程(线程)是操作系统的一个调度实体,进程上下文切换成本较
高,可以通过下面两项计算:
1. 切换开销: Intel E5520: ~4500ns/context switch(csw)
2. CPU cache 失效导致的内存开销
THREADS回顾
问题:
假设一个4核系统有10000个线程正在运行,每个线程每秒处理
10条消息(被调度10次), 问: 一个线程被调度到的最大延迟是多
长?
计算: (只需要按单个核分布的线程数计算)
调度开销 := (1/4 ) * 10 * 10000 * 4500 ns = 113 ms
同时假设:处理每个数据包用1000条指令,每条指令花费1ns,那么最大延迟为:
113ms + 25000 * 1000 * 1ns = 138ms
(注意,以上的计算,并没有计算指令中还有IO的调度,网卡中断,也没有计算
CPU cache失效的开销,实际情况远大于这个。)
THREADS回顾
内存开销:
一个THREAD的基本的内存开销为:2MB的固定长度Stack
计算10000个threads启动需要的基本内存为:
10K * 2M = 20 G
(PS. 进程的Stack 默认是 8M,用ulimit –s 查看)
On Linux/x86-32, the default stack size for a new thread is
2 megabytes.http://man7.org/linux/man-
pages/man3/pthread_create.3.html
GOROUTINE
goroutine是一种轻量级的线程,不是操作系统中的线程,称为纤程更为合适。
goroutine本质上来说只代表一个独立的执行路径,即对应了地址空间中的一个独立
的Call Stack, 这个stack是自增长的。
goroutine对应的结构体如下:
struct G{
uintptr stackguard;
uintptr stackbase;
Defer* defer;
Panic* panic;
Gobuf sched;
uintptr stack0;
…
}
http://golang.org/src/pkg/runtime/runtime.h
GOROUTINE
―goroutine之所以被叫做goroutine,是因为现存
的一些术语——线程、协程和进程等等——都
传达了错误的涵义。‖
—摘自官方文档《Effective Go》
传统IO模型-- SELECT
select()/poll() 可以用于探测一组fd中是否有一个可读或可写,
poll(struct pollfd fds[], nfds_t nfds, int timeout);
因为每次都要传递一组fd到内核,所以其复杂度是O(n),连接数在
1000以内是可以接受的选择,在互联网泡沫破灭之前(<2000年)
是最佳的选择。
PS:select/poll于1986年在SVR3 UNIX出现。
EPOLL
2003年epoll在linux 2.5中出现,称为目前linux服务器的主要使用的
IO模型。
Epoll通过在内核中创建一个专用的结构体,纪录所监控的fd, 一旦
有一个在该fd上触发的事件,那么通知应用程序。
其算法复杂度为O(1),因此其伸缩性极强。
http://en.wikipedia.org/wiki/Epoll
使用GOROUTINE的
网络模型
goroutine相对于thread只有一定的内存开销(最少4K),因此,在
go语言网络模型设计中采用 1:1 的模式,即一个goroutine处理一个
连入的玩家,在内存层面是可以接受的。
计算1万个goroutine需要耗费的stack内存最少为:
4K * 10000 = 40M
GOROUTINE + EPOLL
listener, err := net.ListenTCP("tcp", tcpAddr)
for {
conn, err := listener.Accept()
if err != nil {
continue
}
go handleClient(conn)
}
That's all for a C10K server....
网络接口部分,golang在Linux的IO模型是基于epoll的,并对上层完全透明
因此,网络部分非常简单,并且高效。 (BSD是kqueue实现)
多仸务调度策略
• Cooperative multitasking/time-sharing
协作式: 正在执行的代码片段主动让出CPU,并切换到另一条执
行路径。
• Preemptive multitasking/time-sharing
抢占式(剥夺式): 对正在执行的代码,被操作系统强行中断执
行路径(例如通过时钟中断),并切换到另一个执行路径。
Go语言是典型的协作式,绝大部分用户态的程序,只能做到协作
式,例如LUA的coroutine。
GOROUTINE调度点
1. channel send/recv/select/close (收、发、选、关)
2. malloc (内部内存分配)
3. garbage collection
4. goroutine sleep
5. syscalls (所有系统调用)
基本上,golang的设计在所有可能阻塞的调用中,都尝试主动让出
CPU,让其他任务继续执行。 例如,系统调用 open(),其调度的
有效性,基本等同于操作系统级别(进程遇到阻塞操作会被put to
sleep)。
GOROUTINE的调度延迟
问题:
在一个4核的CPU上,开启10000个goroutine, 平均每个goroutine每
秒处理10个数据包。(假设每个数据包用1000条指令,每条指令花费
1ns)
问:最长响应时间为多长?
计算:
1. 每个CPU平摊 2500个goroutine ,不存在进程切换问题。
2. 最大延迟 := CPU时间 * 2500
即最大延迟为:
1000 * 25000 * 1ns = 25ms
IPC IN
GOLANG
GO语言的IPC
CLASSICAL IPC
PATTERNS
• mutex(互斥) -- pthread_mutex_init()
• rwlock(读写锁) -- pthread_rwlock_init()
• shm (共享内存) -- shm_open()
• semaphore(信号量) -- sem_open()
• pipe(管道) -- pipe()
• socket -- socket
• condwait(条件等待) –- pthread_cond_wait()
• signal(信号) -- kill()
传统的UNIX系统中,以上所有机制在都是由内核提供的功能。
Go语言也提供以上的IPC机制。
IPC相关技术出现的
年代整理
process 60年代早期(冷战早期)
semaphore 1965年由 dijkstra 提出(PV)
signal 1970年在贝尔实验室的Unix系统出现。
pipe 1973年,ken thompson在unix中实现,最初由数学
家 Douglas McIlroy提出
message queue 1980年出现在VRTX和pSOS+(vxworks前生)。
sockets 1983年首次出现于4.2BSD系统,直到1989年才免于
版权保护。
poll 1986年在SVR3 Unix出现。
threads 直到90年代晚期都没有太多的支持,本世纪才普及。
kqueue 2000年在freebsd 4.1中出现。
epoll 2002年在linux 2.5.44中出现。
通信顺序进程(CSP)
CSP := Communication Sequential Processing
is a formal language for describing patterns of interaction in concurrent systems.
一种用于定义并行交互的形式语言.
eg: COPY = *[c:character; west?c → east!c]
CSP was first described in a 1978 paper by C. A. R. Hoare(東尼·霍爾)
• 1980年,获颁图灵奖。
• 1982年,成为英国皇家学会院士。
• 2000年,因为他在计算机科学与教育方面的杰出贡献,获得英国王室颁赠爵士头衔。
(思考:霍爾还做过什么算法?)
CSP定义的交互:
1. 通过Send/Receive实现通信
2. 保证收发同时成功
―不要通过共享内存进行通信. 恰恰相反,通过通
信来共享内存‖
--- Effective Go
CHAN
在go语言中, 提供了一种叫做CHAN的通道,用于goroutine之间交互,CHAN
有两种形式:带缓冲的(有一定的容量)和不带缓冲的,其中不带缓冲的chan
符合CSP的语义,是一种重要的同步机制。
chan类似于pipe(FIFO)的行为,区别在于:
1. pipe是单向的(返回两个fd),一端进,一端出, chan是双向的。
2. pipe没有数据类型的约束,数据也没有边界,chan则可以定义能够传递的
数据类型。
3. 由于历史原因,pipe容量非常有限,只有64K,并且不可调整。
(思考:和message queue有什么关系?)
CSP举例
package main
func main() {
ch := make(chan int,10)
ch <- 1
v := <-ch
println(v)
}
不符合CSP语义, 异步消息
package main
func main() {
ch := make(chan int)
ch <- 1
v := <-ch
println(v)
}
运行出错,但符合CSP语义,
因为收发不可能同时成功
(思考,会报什么错)
CHAN本质是带锁的FIFO队列
发送:
LOCK
ENQUEUE
UNLOCK
接收:
LOCK
DEQUEUE
UNLOCK
GO语言的队列是高效的无锁队列,LOCK操作是基于futex()的。
FUTEX:
现代CPU因为多核的出现,增加了原子操作的指令(如:CAS),新的futex()系统函
数支持这些指令,减轻了传统mutex在内核中调用的消耗(进入内核,进程休眠等),
Go语言中的atomic包提供大量原子操作函数,例如:
CompareAndSwapInt32, AddInt32
.L3:
lock addl $1, foo+4(%rip)
addl $1, -4(%rbp)
原子操作的本质:
锁内存总线
一个基本的消息循环
for {
select {
case msg, ok := <-in: // 来自网络
case msg, ok := <-sess.MQ: // 来自其他goroutine
case _ = <-std_timer: // 定时器
}
}
检查每个case语句:
1. 如果有仸意一个chan是send or recv read,那么就执行该block
2. 如果多个case是ready的,那么随机找1个并执行该block
3. 如果都没有ready,那么就block and wait
4. 如果有default,而且其他的case都没有ready,就执行该default
注意: select channel 没有优先级之分,但能通过调整代码模拟。(思考用什么?)
CHAN OR LOCK?
如果仅能通过chan对某一个数据进行访问,那么,访问是串行的,
相当于数据持有一个mutex。
|REQn| --> | REQn-1| REQn-2|...|REQ1|
在很多高并发读取场景中, 通过channel的并发远远比不上读写锁。
因此,根据实际数据的读写比例,来权衡设计。
CGO & C
用CGO调用C程序
CGO & C
CGO是GO同C语言交互的方法:
package rand
/*
#include <stdlib.h>
*/
import "C"
func Random() int {
return int(C.rand())
}
func Seed(i int) {
C.srand(C.uint(i))
}
有时候我们需要调用一些
C写的程序, 例如嵌入
LUA,以获得脚本的能力。
Go和C的血缘关系,使得
嵌入C非常容易。
目前在github上已经出现
了以golua, luar为代表的
package,使用非常方便。
CGO & C
但是:
由于go的调度机制--协作式的,一旦程序进入C的领域,等于进入
了一个黑盒子,交出了控制权。在C中如果有阻塞的调用,例如
fopen(),那么必然会影响整个go语言的调度。
设计考虑:
1. 在C中(或LUA脚本中),只做CPU运算,绝对不能执行IO阻
塞操作。
2. 运算类的脚本尽量少,脚本执行效率远低于go语言,(慢100
倍以上),响应时间变长。(前面公式)
3. 永远不要忘记释放C中分配的内存。
4. 保持头脑清晰!
一个CGO的应用
$ telnet localhost 8800
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GameServer LUA Console
> a=1
> b=2
> print(a+b)
3
> users = gsdb.ListAll()
> print(users)
[]int32
有时候我们需要像ruby console
那样的灵活性,可以在线的时候
观察,或者改变某些数值。
我们通过CGO嵌入LUA,可以
实现一个类似的Console,在调
试的时候尤其重要。
THANKS
“Embrace the future!”
REFERENCES
http://www.usingcsp.com/cspbook.pdf
http://www.akkadia.org/drepper/futex.pdf
https://docs.google.com/a/nibirutech.com/presentation/d/1Xrv
yfegrkTfqbB3jEwWRtvXGKHuf87UXi8CjMr6n_mc/edit?usp=sharing
gonet框架开源部分:
https://github.com/xtaci/gonet
E-mail: daniel820313@gmail.com
Blog: http://bullshitlie.blogspot.com
Github: https://github.com/xtaci

Weitere ähnliche Inhalte

Was ist angesagt?

lambda/closure – JavaScript、Python、Scala 到 Java SE 7
lambda/closure – JavaScript、Python、Scala 到 Java SE 7lambda/closure – JavaScript、Python、Scala 到 Java SE 7
lambda/closure – JavaScript、Python、Scala 到 Java SE 7Justin Lin
 
程式設計師的自我修養 Chapter 10 記憶體
程式設計師的自我修養 Chapter 10 記憶體程式設計師的自我修養 Chapter 10 記憶體
程式設計師的自我修養 Chapter 10 記憶體Shu-Yu Fu
 
Lua 语言介绍
Lua 语言介绍Lua 语言介绍
Lua 语言介绍gowell
 
shell script introduction
shell script introductionshell script introduction
shell script introductionJie Jin
 
Android C Library: Bionic 成長計畫
Android C Library: Bionic 成長計畫Android C Library: Bionic 成長計畫
Android C Library: Bionic 成長計畫Kito Cheng
 
千呼萬喚始出來的 Java SE 7
千呼萬喚始出來的 Java SE 7千呼萬喚始出來的 Java SE 7
千呼萬喚始出來的 Java SE 7Justin Lin
 
Light talk @ coscup 2011 : Incremental Global Prelink for Android
Light talk @ coscup 2011 : Incremental Global Prelink for AndroidLight talk @ coscup 2011 : Incremental Global Prelink for Android
Light talk @ coscup 2011 : Incremental Global Prelink for AndroidKito Cheng
 
Python 入门
Python 入门Python 入门
Python 入门kuco945
 
Lua gc代码
Lua gc代码Lua gc代码
Lua gc代码Wei Sun
 
Java 開發者的函數式程式設計
Java 開發者的函數式程式設計Java 開發者的函數式程式設計
Java 開發者的函數式程式設計Justin Lin
 
Google protocol buffers简析
Google protocol buffers简析Google protocol buffers简析
Google protocol buffers简析wavefly
 
Analysis of Adobe's RTMFP Protocol
Analysis of Adobe's RTMFP ProtocolAnalysis of Adobe's RTMFP Protocol
Analysis of Adobe's RTMFP ProtocolChangming Sun
 

Was ist angesagt? (20)

lambda/closure – JavaScript、Python、Scala 到 Java SE 7
lambda/closure – JavaScript、Python、Scala 到 Java SE 7lambda/closure – JavaScript、Python、Scala 到 Java SE 7
lambda/closure – JavaScript、Python、Scala 到 Java SE 7
 
程式設計師的自我修養 Chapter 10 記憶體
程式設計師的自我修養 Chapter 10 記憶體程式設計師的自我修養 Chapter 10 記憶體
程式設計師的自我修養 Chapter 10 記憶體
 
Lua 语言介绍
Lua 语言介绍Lua 语言介绍
Lua 语言介绍
 
shell script introduction
shell script introductionshell script introduction
shell script introduction
 
Windbg入门
Windbg入门Windbg入门
Windbg入门
 
Android C Library: Bionic 成長計畫
Android C Library: Bionic 成長計畫Android C Library: Bionic 成長計畫
Android C Library: Bionic 成長計畫
 
軟體工程(總結篇)
軟體工程(總結篇)軟體工程(總結篇)
軟體工程(總結篇)
 
千呼萬喚始出來的 Java SE 7
千呼萬喚始出來的 Java SE 7千呼萬喚始出來的 Java SE 7
千呼萬喚始出來的 Java SE 7
 
Light talk @ coscup 2011 : Incremental Global Prelink for Android
Light talk @ coscup 2011 : Incremental Global Prelink for AndroidLight talk @ coscup 2011 : Incremental Global Prelink for Android
Light talk @ coscup 2011 : Incremental Global Prelink for Android
 
系統程式 -- 第 7 章
系統程式 -- 第 7 章系統程式 -- 第 7 章
系統程式 -- 第 7 章
 
Python 入门
Python 入门Python 入门
Python 入门
 
Lua gc代码
Lua gc代码Lua gc代码
Lua gc代码
 
Execution
ExecutionExecution
Execution
 
Java 開發者的函數式程式設計
Java 開發者的函數式程式設計Java 開發者的函數式程式設計
Java 開發者的函數式程式設計
 
Google protocol buffers简析
Google protocol buffers简析Google protocol buffers简析
Google protocol buffers简析
 
第五章
第五章第五章
第五章
 
系統程式 -- 第 9 章
系統程式 -- 第 9 章系統程式 -- 第 9 章
系統程式 -- 第 9 章
 
Analysis of Adobe's RTMFP Protocol
Analysis of Adobe's RTMFP ProtocolAnalysis of Adobe's RTMFP Protocol
Analysis of Adobe's RTMFP Protocol
 
系統程式 - 附錄
系統程式 - 附錄系統程式 - 附錄
系統程式 - 附錄
 
Clojure的魅力
Clojure的魅力Clojure的魅力
Clojure的魅力
 

Andere mochten auch

Google Go! language
Google Go! languageGoogle Go! language
Google Go! languageAndré Mayer
 
Go language presentation
Go language presentationGo language presentation
Go language presentationparamisoft
 
Write microservice in golang
Write microservice in golangWrite microservice in golang
Write microservice in golangBo-Yi Wu
 
Golang concurrency design
Golang concurrency designGolang concurrency design
Golang concurrency designHyejong
 

Andere mochten auch (6)

Google Go! language
Google Go! languageGoogle Go! language
Google Go! language
 
Go language presentation
Go language presentationGo language presentation
Go language presentation
 
Golang
GolangGolang
Golang
 
Write microservice in golang
Write microservice in golangWrite microservice in golang
Write microservice in golang
 
Golang concurrency design
Golang concurrency designGolang concurrency design
Golang concurrency design
 
Golang vs Ruby
Golang vs RubyGolang vs Ruby
Golang vs Ruby
 

Ähnlich wie Golangintro

Golang 入門初體驗
Golang 入門初體驗Golang 入門初體驗
Golang 入門初體驗政斌 楊
 
Django敏捷开发 刘天斯
Django敏捷开发 刘天斯Django敏捷开发 刘天斯
Django敏捷开发 刘天斯liuts
 
Recycle Open Source Projects
Recycle Open Source ProjectsRecycle Open Source Projects
Recycle Open Source ProjectsGeorge Ang
 
2006 recycle opensourceprojects
2006 recycle opensourceprojects2006 recycle opensourceprojects
2006 recycle opensourceprojectsGeorge Ang
 
Groovy:Candy for Java Developers
Groovy:Candy for Java DevelopersGroovy:Candy for Java Developers
Groovy:Candy for Java Developersfoxgem
 
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫Justin Lin
 
用Erlang构建容错系统
用Erlang构建容错系统用Erlang构建容错系统
用Erlang构建容错系统Cheng Lian
 
2016-04-07-清大-國際化開源專案技術實務與經驗分享
2016-04-07-清大-國際化開源專案技術實務與經驗分享2016-04-07-清大-國際化開源專案技術實務與經驗分享
2016-04-07-清大-國際化開源專案技術實務與經驗分享Jen Yee Hong
 
Grails敏捷项目开发
Grails敏捷项目开发Grails敏捷项目开发
Grails敏捷项目开发Michael Yan
 
KSDG_007_Web 編程另闢蹊徑-GWT,Dart,TypeScript介紹與比較
KSDG_007_Web 編程另闢蹊徑-GWT,Dart,TypeScript介紹與比較KSDG_007_Web 編程另闢蹊徑-GWT,Dart,TypeScript介紹與比較
KSDG_007_Web 編程另闢蹊徑-GWT,Dart,TypeScript介紹與比較Stipc Nsysu
 
4. Go 工程化实践-0124-v2.pdf
4. Go 工程化实践-0124-v2.pdf4. Go 工程化实践-0124-v2.pdf
4. Go 工程化实践-0124-v2.pdfssuserd6c7621
 
Mongo db技术交流
Mongo db技术交流Mongo db技术交流
Mongo db技术交流liuts
 
Hadoop Map Reduce 程式設計
Hadoop Map Reduce 程式設計Hadoop Map Reduce 程式設計
Hadoop Map Reduce 程式設計Wei-Yu Chen
 
数据处理算法设计要点
数据处理算法设计要点数据处理算法设计要点
数据处理算法设计要点thinkinlamp
 
Go 语言国际电子表格文档格式标准实践
Go 语言国际电子表格文档格式标准实践Go 语言国际电子表格文档格式标准实践
Go 语言国际电子表格文档格式标准实践Ri Xu
 

Ähnlich wie Golangintro (20)

Go
GoGo
Go
 
Golang 入門初體驗
Golang 入門初體驗Golang 入門初體驗
Golang 入門初體驗
 
Go Lang
Go LangGo Lang
Go Lang
 
Golang
GolangGolang
Golang
 
Django敏捷开发 刘天斯
Django敏捷开发 刘天斯Django敏捷开发 刘天斯
Django敏捷开发 刘天斯
 
Recycle Open Source Projects
Recycle Open Source ProjectsRecycle Open Source Projects
Recycle Open Source Projects
 
2006 recycle opensourceprojects
2006 recycle opensourceprojects2006 recycle opensourceprojects
2006 recycle opensourceprojects
 
Groovy:Candy for Java Developers
Groovy:Candy for Java DevelopersGroovy:Candy for Java Developers
Groovy:Candy for Java Developers
 
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
 
用Erlang构建容错系统
用Erlang构建容错系统用Erlang构建容错系统
用Erlang构建容错系统
 
2016-04-07-清大-國際化開源專案技術實務與經驗分享
2016-04-07-清大-國際化開源專案技術實務與經驗分享2016-04-07-清大-國際化開源專案技術實務與經驗分享
2016-04-07-清大-國際化開源專案技術實務與經驗分享
 
Grails敏捷项目开发
Grails敏捷项目开发Grails敏捷项目开发
Grails敏捷项目开发
 
KSDG_007_Web 編程另闢蹊徑-GWT,Dart,TypeScript介紹與比較
KSDG_007_Web 編程另闢蹊徑-GWT,Dart,TypeScript介紹與比較KSDG_007_Web 編程另闢蹊徑-GWT,Dart,TypeScript介紹與比較
KSDG_007_Web 編程另闢蹊徑-GWT,Dart,TypeScript介紹與比較
 
4. Go 工程化实践-0124-v2.pdf
4. Go 工程化实践-0124-v2.pdf4. Go 工程化实践-0124-v2.pdf
4. Go 工程化实践-0124-v2.pdf
 
Mongo db技术交流
Mongo db技术交流Mongo db技术交流
Mongo db技术交流
 
Php
PhpPhp
Php
 
Hadoop Map Reduce 程式設計
Hadoop Map Reduce 程式設計Hadoop Map Reduce 程式設計
Hadoop Map Reduce 程式設計
 
数据处理算法设计要点
数据处理算法设计要点数据处理算法设计要点
数据处理算法设计要点
 
Go 语言国际电子表格文档格式标准实践
Go 语言国际电子表格文档格式标准实践Go 语言国际电子表格文档格式标准实践
Go 语言国际电子表格文档格式标准实践
 
Build Your Own Android Toolchain from scratch
Build Your Own Android Toolchain from scratchBuild Your Own Android Toolchain from scratch
Build Your Own Android Toolchain from scratch
 

Golangintro