Go语言编程 (许式伟 等 著)
第1章 初识Go语言
1.1 语言简史
1.2 语言特性
1.2.1 自动垃圾回收
1.2.2 更丰富的内置类型
1.2.3 函数多返回值
1.2.4 错误处理
1.2.5 匿名函数和闭包
1.2.6 类型和接口
1.2.7 并发编程
package main
import "fmt"
func sum(values []int,resultChan chan int) {
sum :=
for _,value := range values {
sum += value
}
resultChan <- sum
}
func main() {
values := [],,,,,,,,,}
resultChan := make(chan )
go sum(values[:len(values)/],resultChan)
go sum(values[len(values)/:],resultChan)
sum1,sum2 := <-resultChan,<-resultChan
fmt.Println("Result:",sum1,sum2,sum1+sum2)
}
paracalc
1.2.8 反射
package main
import (
"fmt"
"reflect"
)
type Bird struct {
Name string
LifeExpectance int
}
func (b *Bird) Fly() {
fmt.Println("I am flying...")
}
func main() {
sparrow := &Bird{}
s := reflect.ValueOf(sparrow).Elem()
typeOfT := s.Type()
; i < s.NumField(); i++ {
f := s.Field(i)
fmt.Printf("%d: %s %s = %v\n",i,typeOfT.Field(i).Name,f.Type(),f.Interface())
}
}
reflect
1.2.9 语言交互性
package main
/*
#include <stdio.h>
*/
import "C"
import "unsafe"
func main() {
cstr := C.CString("Hello,World")
C.puts(cstr)
C.free(unsafe.Pointer(cstr))
}
cprint
1.3 第一个Go程序
package main
import "fmt"
func main() {
fmt.Println("Hello,World")
}
Hello World
1.3.1 代码解读
1.3.2 编译环境准备
$go version
1.3.3 编译程序
1.4 开发工具选择
1.5 工程管理

package main
import "os"
import "fmt"
import "simplemath"
import "strconv"
var Usage = func() {
fmt.Println("USAGE: calc command [arguments] ...")
fmt.Println("\nThe commands are:\n\tadd\tAddition of two values.\n\tsqrt\tSquare
root of a non-negative value.")
}
func main() {
args := os.Args
{
Usage()
return
}
] {
case "add":
{
fmt.Println("USAGE: cacl add <integer1><integer2>")
return
}
v1,err1 := strconv.Atoi(args[])
v2,err2 := strconv.Atoi(args[])
if err1 != nil || err2 != nil {
fmt.Println("USAGE: calc add<integer1><integer2>")
return
}
ret := simplemath.Add(v1,v2)
fmt.Println("Result: ",ret)
case "sqrt":
{
fmt.Println("USAGE: calc sqrt <integer>")
return
}
v,err := strconv.Atoi(args[])
if err != nil {
fmt.Println("USAGE: calc sqrt <integer>")
return
}
ret := simplemath.Sqrt(v)
fmt.Println("Result: ",ret)
default:
Usage()
}
}
calcl
package simplemath
func Add(a int,b int) int {
return a + b
}
add
package simplemath
import "testing"
func TestAdd1(t *testing.T) {
r := Add(,)
{
t.Errorf("Add(1,2) failed.Got %d,expected 3.",r)
}
}
add_test
package simplemath
import "math"
func Sqrt(i int) int {
v := math.Sqrt(float64(i))
return int(v)
}
sqrt
package simplemath
import "testing"
func TestSqrt1(t *testing.T) {
v := Sqrt()
{
t.Errorf("Sqrt(16) failed.Got %v,expected 4.",v)
}
}
sqrt_test
1.6 问题追踪和调试
1.6.1 打印日志
1.6.2 GDB调试
1.7 如何寻求帮助
1.7.1 邮件列表
1.7.2 网站资源
1.8 小结
第2章 顺序编程
2.1 变量
2.1.1 变量声明
var v1 int
var v2 string
]int
var v4 []int
var v5 struct {
f int
}
var v6 *int
var v7 map[string]int
var v8 func(a int) int
var (
v1 int
v2 string
)
varTest1
2.1.2 变量初始化
v3 :=
varTest2
2.1.3 变量赋值
var v10 int v10 = i,j = j,i
varTest3
2.1.4 匿名变量
func GetName() (firstName,lastName,nickName string) {
return "May","Chan","Chibi Maruko"
}
_,_,nickName := GetName()
varTest4
2.2 常量
2.2.1 字面常量
2.2.2 常量定义
const Pi float64 = 3.14159265358979323846
const zero = 0.0
const (
size int64 =
eof = -
)
,
,,"foo"
<<
varTest5
2.2.3 预定义常量
const (
c0 = iota
c1 = iota
c2 = iota
)
const (
a = << iota
b = << iota
c = << iota
)
const (
u = iota *
v float64 = iota *
w = iota *
)
const x = iota
const y = iota
const (
c0 = iota
c1
c2
)
const (
a = << iota
b
c
)
varTest6
2.2.4 枚举
const (
Sunday = iota
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
numberOfDays
)
varTest7
2.3 类型
布尔类型:bool 整型:int8,byte,int16,int,uint,uintptr等 浮点类型:float32,float64 复数类型:complex64,complex128 字符串:string 字符类型:rune 错误类型:error 指针(pointer) 数组(array) 切片(slice) 字典(map) 通道(chan) 结构体(struct) 接口(interface)
类型
2.3.1 布尔类型
2.3.2 整型

2.3.3 浮点型
import "math"
// p为用户定义的比较精度,比如0.00001
func IsEqual(f1,f2,p float64) bool {
return math.Fdim(f1,f2) < p
}
2.3.4 复数类型
2.3.5 字符串
package main
import "fmt"
func main() {
str := "Hello, 世界"
n := len(str)
; i < n; i++ {
ch := str[i]
fmt.Println(i,ch)
}
for i,ch := range str {
fmt.Println(i,ch)
}
}
2.3.6 字符类型
2.3.7 数组
package main
import "fmt"
func Modify(array []int) {
array[] =
fmt.Println("In Modify(),array values:",array)
}
func main() {
array := [],,,,}
Modify(array)
fmt.Println("In main(),array values:",array)
}
2.3.8 数组切片
package main
import "fmt"
func main() {
]],,,,,,,,,}
]
fmt.Println("Elements of myArray: ")
for _,v := range myArray {
fmt.Print(v," ")
}
fmt.Println("\nElements of mySlice: ")
for _,v := range mySlice {
fmt.Print(v," ")
}
fmt.Println()
mySlice1 := make([])
mySlice2 := make([],)
mySlice3 := [],,,,}
}
slice1
package main
import "fmt"
func main() {
mySlice := make([],)
fmt.Println("len(mySlice):",len(mySlice))
fmt.Println("cap(mySlice):",cap(mySlice))
mySlice = append(mySlice,,,)
mySlice2 := [],,}
mySlice = append(mySLice,mySlice2...)
}
slice2
2.3.9 map
package main
import "fmt"
type PersonInfo struct {
ID string
Name string
Address string
}
func main() {
var personDB map[string]PersonInfo
personDB = make(map[string]PersonInfo)
personDB[","Tom","Room 203,..."}
personDB[","Jack","Room 101,..."}
person,ok := personDB["]
if ok {
fmt.Println("Found person",person.Name,"with ID 1234.")
} else {
fmt.Println("Did not find person with ID 1234.")
}
}
map1
2.4 流程控制
2.4.1 条件语句
2.4.2 选择语句
switch i {
:
fmt.Printf(")
:
fmt.Printf(")
:
fallthrough
:
fmt.Printf(")
,,:
fmt.Printf("4,5,6"")
default:
fmt.Printf("Default")
}
switch {
<= Num && Num <= :
fmt.Printf("0-3")
<= Num && Num <= :
fmt.Printf("4-6")
<= NUM && Num <= :
fmt.Printf("7-9")
}
switch
2.4.3 循环语句
sum :=
; i < ; i++ {
sum += i
}
sum :=
for {
sum ++
{
break
}
}
a := [],,,,,}
, len(a) - ; i < j;i,j = i + , j - {
a[i],a[j] = a[j],a[i]
}
; j < ; j++ {
; i < ; i++ {
{
break JLoop
}
fmt.Println(i)
}
}
JLoop:
for
2.4.4 跳转语句
func myfunc() {
i :=
HERE:
fmt.Println(i)
i++
{
goto HERE
}
}
goto
2.5 函数
2.5.1 函数定义
2.5.2 函数调用
2.5.3 不定参数
package main
import "fmt"
func MyPrintf(args ...interface{}) {
for _,arg := range args {
switch arg.(type) {
case int:
fmt.Println(arg,"is an int value.")
case string:
fmt.Println(arg,"is a string value.")
case int64:
fmt.Println(arg,"is an int64 value.")
default:
fmt.Println(arg,"is an unknown type.")
}
}
}
func main() {
var v3 string = "hello"
var v4 float32 = 1.234
MyPrintf(v1,v2,v3,v4)
}
varg1
2.5.4 多返回值
2.5.5 匿名函数与闭包
package main
import "fmt"
func main() {
a := func()(func()) {
return func() {
fmt.Printf("i,j:%d,%d\n",i,j)
}
}()
a()
j *=
a()
}
closure
2.6 错误处理
2.6.1 error接口
2.6.2 defer
2.6.3 panic()和recover()
2.7 完整示例
2.7.1 程序结构
2.7.2 主程序
2.7.3 算法实现
2.7.4 主程序
2.7.5 构建与执行
2.8 小结
第3章 面向对象编程
3.1 类型系统
3.1.1 为类型添加方法
package main
import "fmt"
type Integer int
func (a Integer) Less(b Integer) bool {
return a < b
}
func (a *Integer) Add(b Integer) {
*a += b
}
func (a Integer) Add1(b Integer) {
a += b
}
func main() {
) {
fmt.Println(a,"Less 2")
}
a.Add()
fmt.Println("a = ",a)
a.Add1()
fmt.Println("a = ",a)
}
3.1.2 值语义和引用语义
3.1.3 结构体
3.2 初始化
3.3 匿名组合
3.4 可见性
3.5 接口
3.5.1 其他语言的接口
3.5.2 非侵入式接口
type File struct {
}
func (f *File) Read(buf []byte) (n int,err error)
func (f *File) Write(buf []byte) (n int,err error)
func (f *File) Seek(off int64,whence int) (pos int64,err error)
func (f *File) Close() error
type IFile interface {
Read(buf []byte) (n int,err error)
Write(buf []byte) (n int,err error)
Seek(off int64,whence int) (pos int64,err error)
Close() error
}
type IReader interface {
Read(buf []byte) (n int,err error)
}
type IWriter interface {
Write(buf []byte) (n int,err error)
}
type ICloser interface {
Close() error
}
var file1 IFile = new(File)
var file2 IReader = new(File)
var file3 IWriter = new(File)
var file4 ICloser = new(File)
3.5.3 接口赋值
package one
type ReadWriter interface {
Read(buf []byte) (n int,err error)
Write(buf []byte) (n int,err error)
}
package two
type IStream interface {
Write(buf []byte) (n int,err error)
Read(buf []byte) (n int,err error)
}
var file1 two.IStream = new (File)
var file2 one.ReadWriter = file1
var file3 two.IStream = file2
type Writer interface {
Write(buf []byte) (n int err error)
}
var file1 two.IStream = new(File)
var file4 Writer = file1
var file1 Writer = new(File)
var file5 two.IStream = file1 // 编译不能通过
3.5.4 接口查询
var file1 Writer = ...
if file5,ok := file1.(two.IStream); ok {
...
}
var file1 Writer = ...
if file6,ok := file1.(*File); ok {
...
}
3.5.5 类型查询
3.5.6 接口组合
3.5.7 Any类型
3.6 完整示例
3.6.1 音乐库
3.6.2 音乐播放
3.6.3 主程序
3.6.4 构建运行
3.6.5 遗留问题
3.7 小结
第4章 并发编程
4.1 并发基础
4.2 协程
4.3 goroutine
package main
import "fmt"
func Add(x,y int) {
z := x + y
fmt.Println(z)
}
func main() {
; i < ; i++ {
go Add(i,i)
}
}
add
4.4 并发通信
package main
import "fmt"
import "sync"
import "runtime"
func Count(lock *sync.Mutex) {
lock.Lock()
counter++
fmt.Println(counter)
lock.Unlock()
}
func main() {
lock := &sync.Mutex{}
; i < ; i++ {
go Count(lock)
}
for {
lock.Lock()
c := counter
lock.Unlock()
runtime.Gosched()
{
break
}
}
}
thread
4.5 channel
package main
import "fmt"
func Count(ch chan int) {
ch <-
fmt.Println("Counting")
}
func main() {
chs := make([]chan )
;i < ; i++ {
chs[i] = make(chan int)
go Count(chs[i])
}
for _,ch := range(chs) {
<-ch
}
}
channel
4.5.1 基本语法
var chanName chan ElementType var ch chan int var m map[string]chan bool ch := make(chan int) ch <- value // 写入channel value := <-ch // 读取channel
4.5.2 select
select {
case <-chan1:
// 如果chan1成功读取数据,则进行该case处理语句
:
// 如果成功向chan2写入数据,则进行该case处理语句
default:
// 如果上面都没有成功,则进入default处理流程
}
ch := make(chan )
for {
select {
:
:
}
i := <-ch
fmt.Println("Value received:",i)
}
4.5.3 缓冲机制
4.5.4 超时机制
// 首先,我们实现并执行一个匿名的超时等待函数
timeout := make(chan )
go func() {
time.Sleep(1e9) // 等待一秒钟
timeout <- true
}()
// 然后我们把timeout这个channel利用起来
select {
case <-ch:
// 从ch中读取到数据
case <-timeout:
// 一致没有从ch中读取到数据,但从timeout中读取到了数据
}
4.5.5 channel的传递
type PipeData struct {
value int
handler func(int) int
next chan int
}
func handle(queue chan *PipeData) {
for data := range queue {
data.next <- data.handler(data.value)
}
}
4.5.6 单向channel
var ch1 chan int var ch2 chan<- float64 var ch3 <-chan int ch4 := make(chan int) ch5 := <-chan int(ch4) ch6 := chan<- int(ch4)
4.5.7 关闭channel
close(ch) x,ok := <-ch
4.6 多核并行化
type Vector []float64
func(v Vector) DoSome(i,n int,u Vector,c chan int) {
for ;i < n;i++ {
v[i] += u.Op(v[i])
}
c <-
}
func (v Vector) DoAll(u Vecotr) {
c := make(chan int,NCPU)
;i < NCPU;i++ {
go v.DoSome(i*len(v)/NCPU,(i+)*len(v)/NCPU,u,c)
}
;i < NCPU;i++ {
<-c
}
}
runtime.GOMAXPROCS()
4.7 出让时间片
4.8 同步
4.8.1 同步锁
4.8.2 全局唯一性操作
var a string
var once sync.Once
func setup() {
a = "hello,world"
}
func dropint() {
once.Do(setup)
print(a)
}
func twoprint() {
go doprint()
go dropinit()
}
4.9 完整示例
4.9.1 简单IPC框架
4.9.2 中央服务器
4.9.3 主程序
4.9.4 运行小程序
4.10 小结
第5章 网络编程
5.1 Socket编程
5.1.1 Dial()函数
5.1.2 ICMP示例程序
5.1.3 TCP示例程序
package main
import (
"net"
"os"
"bytes"
"fmt"
"io"
)
func main() {
{
fmt.Fprintf(os.Stderr,])
os.Exit()
}
service := os.Args[]
conn,err := net.Dial("tcp",service)
checkError(err)
_,err = conn.Write([]byte("HEAD / HTTP/1.0\r\n\r\n"))
checkError(err)
result,err := readFully(conn)
checkError(err)
fmt.Println(string(result))
os.Exit()
}
func checkError(err error) {
if err != nil {
fmt.Fprintf(os.Stderr,"Fatal error: %s",err.Error())
os.Exit()
}
}
func readFully(conn net.Conn) ([]byte,error) {
defer conn.Close()
result := bytes.NewBuffer(nil)
]byte
for {
n,err := conn.Read(buf[:])
result.Write(buf[:n])
if err != nil {
if err == io.EOF {
break
}
return nil,err
}
}
return result.Bytes(),nil
}
simplehttp
5.1.4 更丰富的网络通信
//func DialTCP(net string,laddr,raddr *TCPAddr) (c *TCPConn,err error)
//func DialUDP(net string,laddr,raddr *UDPAddr) (c *UDPConn,err error)
//func DialIP(netProto string,laddr,raddr *IPAddr) (*IPConn,error)
//func DialUnix(net string,laddr,raddr *UnixAddr) (c *UnixConn,err error)
package main
import (
"net"
"os"
"fmt"
"io/ioutil"
)
func main() {
{
fmt.Fprintf(os.Stderr,])
os.Exit()
}
service := os.Args[]
tcpAddr,err := net.ResolveTCPAddr("tcp4",service)
checkError(err)
conn,err := net.DialTCP("tcp",nil,tcpAddr)
checkError(err)
_,err = conn.Write([]byte("HEAD / HTTP1.0\r\n\r\n"))
checkError(err)
result,err := ioutil.ReadAll(conn)
checkError(err)
fmt.Println(string(result))
os.Exit()
}
func checkError(err error) {
if err != nil {
fmt.Fprintf(os.Stderr,"Fatal error: %s",err.Error())
os.Exit()
}
}
simplehttp2
5.2 HTTP编程
5.2.1 HTTP客户端
package main
import (
"net/http"
)
type OurCustomTransport struct {
Transport http.RoundTripper
}
func (t *OurCustomTransport) transport() http.RoundTripper {
if t.Transport != nil {
return t.Transport
}
return http.DefaultTransport
}
func (t *OurCustomTransport) RoundTrip(req *http.Request) (*http.Response,error) {
// 处理一些事情
// 发起HTTP请求
// 添加一些域到req.Header中
return t.transport().RoundTrip(req)
}
func (t *OurCustomTransport) Client() *http.Client {
return &http.Client{Transport:t}
}
func main() {
t := &OurCustomTransport {
//...
}
c := t.Client()
resp,err := c.Get("http://example.com")
// ...
}
customtrans
5.2.2 HTTP服务端
5.3 RPC编程
5.3.1 Go语言中的RPC支持与处理
5.3.2 Gob简介
5.3.3 设计优雅的RPC接口
5.4 JSON处理
5.4.1 编码为JSON格式
func Marshal(v interface{}) ([]byte,error)
type Book struct {
Title string
Authors []string
Publisher string
IsPublished bool
Price float
}
gobook := Book {
"Go语言编程",
["XuShiwei","HughLv"],
"ituring.com.cn",
true,
9.99
}
b,err := json.Marshal(gobook)
b == []byte('{
"Title":"Go语言编程",
"Authors":["XuShiwei","HughLv"],
"Publisher":"ituring.com.cn",
"IsPublished":true,
"Price":9.99
}')
5.4.2 解码JSON数据
func Unmarshal(data []byte,v interface{}) error
var book Book
err := json.Unmarshal(b,&book)
book := Book{
"Go语言编程“,
["XuShiwei","HughLv"],
"ituring.com.cn",
true,
9.99
}
b := []byte('{"Title":"Go语言编程","Sales":100000}')
var gobook Book
err := json.Unmarshal(b,&gobook)
5.4.3 解码未知结构的JSON数据
b := []byte('{
"Title":"Go语言编程",
"Authors":["XuShiwei",HughLv"],
"Publisher":"ituring.com.cn",
"IsPublished":true,
"Price":9.99,
}')
var r interface{}
err := json.Unmarshal(b,&r)
map[string]interface{}{
"Title":"Go语言编程",
"Authors":["XuShiwei",HughLv"],
"Publisher":"ituring.com.cn",
"IsPublished":true,
"Price":9.99,
}
gobook,ok := r.(map[string]interface{})
if ok {
for k,v := range gobook {
switch v2 := v.(type) {
case string:
fmt.Println(k,"is string",v2)
case int:
fmt.Println(k,"is int",v2)
case bool:
fmt.Println(k,"is bool",v2)
case []interface{}:
fmt.Println(k,"is an array:")
for i,iv := range v2 {
fmt.Println(i,iv)
}
default:
fmt.Println(k,"is another type not handle yet")
}
}
}
5.4.4 JSON的流式读写
package main
import (
"encoding/json"
"log"
"os"
)
func main() {
dec := json.NewDecoder(os.Stdin)
enc := json.NewEncoder(os.Stdout)
for {
var v map[string]interface{}
if err := dec.Decode(&v); err != nil {
log.Println(err)
}
for k := range v {
if k != "Title" {
v[k] = nil,false
}
}
if err := enc.Encode(&v); err != nil {
log.Println(err)
}
}
}
jsondemo
5.5 网站开发
5.5.1 最简单的网站程序
package main
import (
"io"
"log"
"net/http"
)
func helloHandler(w http.ResponseWriter,r *http.Request) {
io.WriteString(w,"Hello,world!")
}
func main() {
http.HandleFunc("/hello",helloHandler)
err := http.ListenAndServe(":8080",nil)
if err != nil {
log.Fatal("ListenAndServ: ",err.Error())
}
}
hello
5.5.2 net/http包简介
5.5.3 开发一个简单的相册网站
5.6 小结
第6章 安全编程
6.1 数据加密
6.2 数字签名
6.3 数字证书
6.4 PKI体系
package main
import (
"fmt"
"crypto/sha1"
"crypto/md5"
)
func main() {
TestString := "Hi,pandaman!"
Md5Inst := md5.New()
Md5Inst.Write([]byte(TestString))
Result := Md5Inst.Sum([]byte(""))
fmt.Printf("%x\n\n",Result)
Sha1Inst := sha1.New()
Sha1Inst.Write([]byte(TestString))
Result = Sha1Inst.Sum([]byte(""))
fmt.Printf("%x\n\n",Result)
}
hash1
package main
import (
"io"
"fmt"
"os"
"crypto/md5"
"crypto/sha1"
)
func main() {
TestFile := "123.txt"
infile,inerr := os.Open(TestFile)
if inerr == nil {
md5h := md5.New()
io.Copy(md5h,infile)
fmt.Printf("%x %s\n",md5.Sum([]byte("")),TestFile)
sha1h := sha1.New()
io.Copy(sha1h,infile)
fmt.Printf("%x %s\n",sha1h.Sum([]byte("")),TestFile)
} else {
fmt.Println(inerr)
os.Exit()
}
}
hash2
6.5 Go语言的哈希函数
6.6 加密通道
6.6.1 加密通信流程
6.6.2 支持HTTPS的Web服务器
package main
import (
"fmt"
"net/http"
)
const SERVER_DOMAIN = "localhost"
const RESPONSE_TEMPLATE = "hello"
func rootHandler(w http.ResponseWriter,req *http.Request) {
w.Header().Set("Content-Type","text/html")
w.Header().Set("Content-Length",fmt.Sprint(len(RESPONSE_TEMPLATE)))
w.Write([]byte(RESPONSE_TEMPLATE))
}
func main() {
http.HandleFunc(fmt.Sprintf("%s:%d/",SERVER_DOMAIN,SERVER_PORT),rootHandler)
http.ListenAndServeTLS(fmt.Sprintf(":%d",SERVER_PORT),"rui.crt","rui.key",nil)
}
https
package main
import (
"net"
"net/http"
"time"
"fmt"
"crypto/x509"
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"encoding/pem"
"errors"
"io/ioutil"
)
const SERVER_DOMAIN = "localhost"
const RESPONSE_TEMPLATE = "hello"
func rootHandler(w http.ResponseWriter,req *http.Request) {
w.Header().Set("Content-Type","text/html")
w.Header().Set("Content-Length",fmt.Sprint(len(RESPONSE_TEMPLATE)))
w.Write([]byte(RESPONSE_TEMPLATE))
}
func YourListenAndServeTLS(addr string,certFile string,keyFile string,handler http.Handler) error {
config := &tls.Config {
Rand: rand.Reader,
Time: time.Now,
NextProtos: []string{"http/1.1."},
}
var err error
config.Certificates = make([]tls.Certificate,)
config.Certificates[],err = YourLoadX509KeyPair(certFile,keyFile)
if err != nil {
return err
}
conn,err := net.Listen("tcp",addr)
if err != nil {
return err
}
tlsListener := tls.NewListener(conn,config)
return http.Serve(tlsListener,handler)
}
func YourLoadX509KeyPair(certFile string,keyFile string) (cert tls.Certificate,err error) {
certPEMBlock,err := ioutil.ReadFile(certFile)
if err != nil {
return
}
certDERBlock,restPEMBlock := pem.Decode(certPEMBlock)
if certDERBlock == nil {
err = errors.New("crypto/tls: failed to parse certificate PEM data")
return
}
certDERBlockChain,_ := pem.Decode(restPEMBlock)
if certDERBlockChain == nil {
cert.Certificate = [][]byte{certDERBlock.Bytes}
} else {
cert.Certificate = [][]byte{certDERBlock.Bytes,certDERBlockChain.Bytes}
}
keyPEMBlock,err := ioutil.ReadFile(keyFile)
if err != nil {
return
}
keyDERBlock,_ := pem.Decode(keyPEMBlock)
if keyDERBlock == nil {
err = errors.New("crypto/tls: failed to parse key PEM data")
return
}
key,err := x509.ParsePKCS1PrivateKey(keyDERBlock.Bytes)
if err != nil {
err = errors.New("crypto/tls: failed to parse key")
return
}
cert.PrivateKey = key
x509Cert,err := x509.ParseCertificate(certDERBlock.Bytes)
if err != nil {
return
}
{
err = errors.New("crypto/tls: private key does not match public key")
return
}
return
}
func main() {
http.HandleFunc(fmt.Sprintf("%s:%d/",SERVER_DOMAIN,SERVER_PORT),rootHandler);
YourListenAndServeTLS(fmt.Sprintf(":%d",SERVER_PORT),"rui.crt","rui.key",nil)
}
https2
6.6.3 支持HTTPS的文件服务器
package main
import (
"net/http"
)
func main() {
h := http.FileServer(http.Dir("."))
http.ListenAndServeTLS(":8001","rui.crt","rui.key",h)
}
httpsfile
6.6.4 基于SSL/TLS的ECHO程序
6.7 小结
第7章 工程管理
7.1 Go命令行工具
7.2 代码风格
7.2.1 强制性编码规范
7.2.2 非强制性编码风格建议
package main
import "fmt"
func Foo(a,b int)(ret int,err error){
if a > b{
return a,nil
}else{
return b,nil
}
,nil
}
func
main() { i,_ := Foo(,)
fmt.Println("Hello,world",i)}
hello1
$ go fmt hello1.go
package main
import "fmt"
func Foo(a, b int) (ret int, err error) {
if a > b {
return a, nil
} else {
return b, nil
}
, nil
}
func main() {
i, _ := Foo(, )
fmt.Println("Hello,world", i)
}
test2
7.3 远程import支持
package main
import (
"fmt"
"github.com/myteam/exp/crc32"
)
7.4 工程组织
7.4.1 GOPATH
export GOPATH=~/work/go-proj1:~/work2/goproj2:~/work3/work4/go-proj3
7.4.2 目录结构
7.5 文档管理
7.6 工程构建
7.7 跨平台开发
7.7.1 交叉编译
7.7.2 Android支持
7.8 单元测试
7.9 打包分发
7.10 小结
第8章 开发工具
8.1 选择开发工具
8.2 gedit
8.2.1 语法高亮
8.2.2 编译环境
8.3 Vim
8.4 Eclipse
8.5 Notepad++
8.5.1 语法高亮
8.5.2 编译环境
8.6 LitelIDE
8.7 小结
第9章 进阶话题
9.1 反射
9.1.1 基本概念
9.1.2 基本用法
package main
import (
"fmt"
"reflect"
)
func main() {
var x float64 = 3.4
fmt.Println("type:",reflect.TypeOf(x))
v := reflect.ValueOf(x)
fmt.Println("type:",v.Type())
fmt.Println("kind is float64:",v.Kind() ==reflect.Float64)
fmt.Println("value:",v.Float())
}
reflect
package main
import (
"fmt"
"reflect"
)
func main() {
var x float64 = 3.4
p := reflect.ValueOf(&x)
fmt.Println("type of p:",p.Type())
fmt.Println("settability of p:",p.CanSet())
v := p.Elem()
fmt.Println("settability of v:",v.CanSet())
v.SetFloat(7.1)
fmt.Println(v.Interface())
fmt.Println(x)
}
9.1.3 对结构的反射操作
package main
import (
"fmt"
"reflect"
)
type T struct {
A int
B string
}
func main() {
t := T{,"mh203"}
s := reflect.ValueOf(&t).Elem()
typeOfT := s.Type()
; i < s.NumField(); i++ {
f := s.Field(i)
fmt.Printf("%d: %s %s = %v\n",i,typeOfT.Field(i).Name,f.Type(),f.Interface())
}
}
9.2 语言交互性
package main
import "fmt"
/*
#include <stdlib.h>
*/
import "C"
func Random() int {
return int(C.random())
}
func Seed(i int) {
C.srandom(C.uinit(i))
}
func main() {
Seed()
fmt.Println("Random:",Random())
}
cgo1
package main
/*
#include <stdio.h>
void hello() {
printf("Hello,Cgo! -- From C world.\n")
}
*/
import "C"
func Hello() int {
return int(C.hello())
}
func main() {
Hello()
}
// #cgo CFLAGS: -DPNG_DEBUG=1
// #cgo linux CFLAGS: -DLINUX=1
// #cgo LDFLAGS: -lpng
// #include <png.h>
import "C"
// #cgo pkg-config: png cairo
// #include <png.h>
import "C"
cgo2
9.2.1 类型映射
9.2.2 字符串映射
9.2.3 C程序
9.2.4 函数调用
9.2.5 编译Cgo
9.3 链接符号
9.4 goroutine机理
9.4.1 携程
9.4.2 携程的C语言实现
9.4.3 协程库概述
package main
import (
"flag"
"fmt"
"os"
"strconv"
)
var goal int
func primeTask(c chan int) {
p := <-c
if p > goal {
os.Exit()
}
fmt.Println(p)
nc := make(chan int)
go primeTask(nc)
for {
i := <-c
{
nc <- i
}
}
}
func main() {
flag.Parse()
args := flag.Args()
{
var err error
goal,err = strconv.Atoi(args[])
if err != nil {
goal =
}
} else {
goal =
}
fmt.Println("goal=",goal)
c := make(chan int)
go primeTask(c)
;;i++ {
c <- i
}
}
primes
9.4.4 任务
9.4.5 任务调度
9.4.6 上下文切换
9.4.7 通信机制
9.5 接口机理
9.5.1 类型赋值给接口
package main
import "fmt"
type ISpeaker interface {
Speak()
}
type SimpleSpeaker struct {
Message string
}
func (speaker *SimpleSpeaker) Speak() {
fmt.Println("I am speaking? ",speaker.Message)
}
func main() {
var speaker ISpeaker
speaker = &SimpleSpeaker{"Hell"}
speaker.Speak()
}
interface-1
9.5.2 接口查询
9.5.3 接口赋值
Go语言编程 (许式伟 等 著)的更多相关文章
- 许式伟:我与Go语言的这十年[转]
2017-12-18 许式伟 Go中国 2007 年 9 月 20 日,关于设计一门全新语言的讨论正式开始,这门全新的语言,就是后来的 Go.时至今日,Go 语言已经发布到 1.9 版本,走过了整整十 ...
- TOP100summit 2017 七牛云许式伟:不用JAVA和C语言,我为什么坚持Go语言
本文编辑:Cynthia 2009年,谷歌发布第二款开源编程语言,Go语言.8年过去了,很多初创公司早期使用Go进行开发,包括云计算巨头Docker.而Go语言在中国的普及程度还比不上JAVA和C语言 ...
- C语言编程实现Linux命令——who
C语言编程实现Linux命令--who 实践分析过程 who命令是查询当前登录的每个用户,它的输出包括用户名.终端类型.登录日期及远程主机,在Linux系统中输入who命令输出如下: 我们先man一下 ...
- 个人c语言编程风格总结
总结一下我个人的编程风格及这样做的原因吧,其实是为了给实验室写一个统一的C语言编程规范才写的.首先声明,我下面提到的编程规范,是自己给自己定的,不是c语言里面规定的. 一件事情,做成和做好中间可能隔了 ...
- Linux下C语言编程实现spwd函数
Linux下C语言编程实现spwd函数 介绍 spwd函数 功能:显示当前目录路径 实现:通过编译执行该代码,可在终端中输出当前路径 代码实现 代码链接 代码托管链接:spwd.c 所需结构体.函数. ...
- 七牛CEO许式伟:移动游戏资源存贮的大趋势
(国内知名Android开发论坛eoe开发者社区推荐:http://www.eoeandroid.com/) 9月14日,eoe移动开发者大会正式在北京国家会议中心召开,七牛云储存CEO许式伟先生做了 ...
- 混合语言编程:启用CLR(公共语言运行时编译)让C#调用C++
前言 关于混合C#和C++的编程方式,本人之前写过一篇博客(参见混合语言编程:C#使用原生的Directx和OpenGL),在之前的博客中,介绍了在C#的Winform和WPF下使用原生的Direct ...
- Linux基础与Linux下C语言编程基础
Linux基础 1 Linux命令 如果使用GUI,Linux和Windows没有什么区别.Linux学习应用的一个特点是通过命令行进行使用. 登录Linux后,我们就可以在#或$符后面去输入命令,有 ...
- LINUX下C语言编程基础
实验二 Linux下C语言编程基础 一.实验目的 1. 熟悉Linux系统下的开发环境 2. 熟悉vi的基本操作 3. 熟悉gcc编译器的基本原理 4. 熟练使用gcc编译器的常用选项 5 .熟练使用 ...
随机推荐
- Bluedroid: 音频数据的传输流程
一. UIPC: Audio Flinger获取到a2dp的hw module,然后蓝牙协议栈有专用于发送和接收media数据的线程,名称:btif_media_task. 蓝牙与Audio的 ...
- Batch Normalization 引出的一系列问题
Batch Normalization,拆开来看,第一个单词意思是批,出现在梯度下降的概念里,第二个单词意思是标准化,出现在数据预处理的概念里. 我们先来看看这两个概念. 数据预处理 方法很多,后面我 ...
- ios轮播图片用法
// // ZQRViewController.m // 04-图片轮播器 // // Created by apple on 17-08-24. // Copyright (c) 2017年 zzq ...
- Vue extend 学习
<div id="box"> <aa></aaa> </div> <script> var Aaa = Vue.exte ...
- HTC脚本介绍和入门示例
一.简介 HTC脚本全称是Html Companent即html组件,个人认为它是为了在开发动态HTML中实现代码重用和页面共享目的,主要是把“行为”作为组件封装,可以在很大程度上简化DHTML的开发 ...
- python里的函数
map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回. 假设用户输入的英文名字不规范, ...
- 【Python】unittest-3
一.@unittest.skip("skipping this case") # 无条件忽略该测试方法 二.@unittest.skipIf(a > 5, "con ...
- 【Python】进程-锁(1)
#第二题,做一个加减乘除的考试系统,自动出题,自动判对错,并统计结果,一次考试10道题 import random symbols=["+","-"," ...
- 【计算机视觉】KCF算法
code opencv3.3.1-contrib ---- TrackerKCF.cpp opencv如何更新目标区域的过程: // calculate filter response if(par ...
- python import 其他 package的模块
https://blog.csdn.net/luo123n/article/details/49849649 http://blog.habnab.it/blog/2013/07/21/python- ...