第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 mainimport "fmt"func sum(values []int,resultChan chan int) {sum := 0for _,value := range values {sum += value}resultChan <- sum
}func main() {values := []int {1,2,3,4,5,6,7,8,9,10}resultChan := make(chan int,2)go sum(values[:len(values)/2],resultChan)go sum(values[len(values)/2:],resultChan)sum1,sum2 := <-resultChan,<-resultChanfmt.Println("Result:",sum1,sum2,sum1+sum2)
}

paracalc

    1.2.8 反射

package mainimport ("fmt""reflect"
)type Bird struct {Name stringLifeExpectance int
}func (b *Bird) Fly() {fmt.Println("I am flying...")
}func main() {sparrow := &Bird{"Sparrow",3}s := reflect.ValueOf(sparrow).Elem()typeOfT := s.Type()for i := 0; 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 mainimport "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 mainimport "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\tSquareroot of a non-negative value.")
}func main() {args := os.Argsif args == nil || len(args) < 2 {Usage()return}switch args[0] {case "add":if len(args) != 3 {fmt.Println("USAGE: cacl add <integer1><integer2>")return}v1,err1 := strconv.Atoi(args[1])v2,err2 := strconv.Atoi(args[2])if err1 != nil || err2 != nil {fmt.Println("USAGE: calc add<integer1><integer2>")return}ret := simplemath.Add(v1,v2)fmt.Println("Result: ",ret)case "sqrt":if len(args) != 2 {fmt.Println("USAGE: calc sqrt <integer>")return}v,err := strconv.Atoi(args[1])if err != nil {fmt.Println("USAGE: calc sqrt <integer>")return}ret := simplemath.Sqrt(v)fmt.Println("Result: ",ret)default:Usage()}
}

calcl

package simplemathfunc Add(a int,b int) int {return a + b
}

add

package simplemathimport "testing"func TestAdd1(t *testing.T) {r := Add(1,2)if r != 3 {t.Errorf("Add(1,2) failed.Got %d,expected 3.",r)}
}

add_test

package simplemathimport "math"func Sqrt(i int) int {v := math.Sqrt(float64(i))return int(v)
}

sqrt

package simplemathimport "testing"func TestSqrt1(t *testing.T) {v := Sqrt(16)if v != 4 {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
var v3 [10]int
var v4 []int
var v5 struct {f int
}
var v6 *int
var v7 map[string]int
var v8 func(a int) intvar (v1 intv2 string
)

varTest1

    2.1.2 变量初始化

var v1 int = 10
var v2 = 10
v3 := 10

varTest2

    2.1.3 变量赋值

var v10 int
v10 = 123i,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 = 1024eof = -1
)
const u,v float32 = 0,3
const a,b,c = 3,4,"foo"
const mask = 1 << 3

varTest5

    2.2.3 预定义常量

const (c0 = iotac1 = iotac2 = iota
)const (a = 1 << iotab = 1 << iotac = 1 << iota
)const (u = iota * 42v float64 = iota * 42w = iota * 42
)const x = iota
const y = iotaconst (c0 = iotac1c2
)const (a = 1 << iotab c
)

varTest6

    2.2.4 枚举

const (Sunday = iotaMondayTuesdayWednesdayThursdayFridaySaturdaynumberOfDays
)

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
}

View Code

    2.3.4 复数类型

    2.3.5 字符串

package mainimport "fmt"func main() {str := "Hello, 世界"n := len(str)for i := 0; i < n; i++ {ch := str[i]fmt.Println(i,ch)}for i,ch := range str {fmt.Println(i,ch)}
}

View Code

    2.3.6 字符类型

    2.3.7 数组

package mainimport "fmt"func Modify(array [5]int) {array[0] = 10fmt.Println("In Modify(),array values:",array)
}func main() {array := [5]int{1,2,3,4,5}Modify(array)fmt.Println("In main(),array values:",array)
}

View Code

    2.3.8 数组切片

package mainimport "fmt"func main() {var myArray [10]int = [10]int{1,2,3,4,5,6,7,8,9,10}var mySlice []int = myArray[:5]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([]int,5)mySlice2 := make([]int,5,10)mySlice3 := []int{1,2,3,4,5}
}

slice1

package mainimport "fmt"func main() {mySlice := make([]int,5,10)fmt.Println("len(mySlice):",len(mySlice))fmt.Println("cap(mySlice):",cap(mySlice))mySlice = append(mySlice,1,2,3)mySlice2 := []int{8,9,10}mySlice = append(mySLice,mySlice2...)
}

slice2

    2.3.9 map

package mainimport "fmt"type PersonInfo struct {ID stringName stringAddress string
}func main() {var personDB map[string]PersonInfopersonDB = make(map[string]PersonInfo)personDB["12345"] = PersonInfo{"12345","Tom","Room 203,..."}personDB["1"] = PersonInfo{"1","Jack","Room 101,..."}person,ok := personDB["1234"]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 {case 0:fmt.Printf("0")case 1:fmt.Printf("1")case 2:fallthroughcase 3:fmt.Printf("3")case 4,5,6:fmt.Printf("4,5,6"")default:fmt.Printf("Default")
}switch {case 0 <= Num && Num <= 3:fmt.Printf("0-3")case 4 <= Num && Num <= 6:fmt.Printf("4-6")case 7 <= NUM && Num <= 9:fmt.Printf("7-9")
}

switch

    2.4.3 循环语句

sum := 0
for i :=0; i < 10; i++ {sum += i
}sum := 0
for {sum ++if sum > 100 {break}
}a := []int{1,2,3,4,5,6}
for i,j := 0, len(a) - 1; i < j;i,j = i + 1, j - 1 {a[i],a[j] = a[j],a[i]
}for j := 0; j < 5; j++ {for i := 0; i < 10; i++ {if i > 5 {break JLoop}fmt.Println(i)}
}
JLoop:

for

    2.4.4 跳转语句

func myfunc() {i := 0HERE:fmt.Println(i)i++if i < 10 {goto HERE}
}

goto

  2.5 函数

    2.5.1 函数定义

    2.5.2 函数调用

    2.5.3 不定参数

package mainimport "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 v1 int = 1var v2 int64 = 234var v3 string = "hello"var v4 float32 = 1.234MyPrintf(v1,v2,v3,v4)
}

varg1

    2.5.4 多返回值

    2.5.5 匿名函数与闭包

package mainimport "fmt"func main() {var j int = 5a := func()(func()) {var i int = 10return func() {fmt.Printf("i,j:%d,%d\n",i,j)}}()a()j *= 2a()
}

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 mainimport "fmt"type Integer intfunc (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() {var a Integer = 1if a.Less(2) {fmt.Println(a,"Less 2")}a.Add(2)fmt.Println("a = ",a)a.Add1(2)fmt.Println("a = ",a)
}

View Code

    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() errortype 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)

View Code

    3.5.3 接口赋值

package onetype ReadWriter interface {Read(buf []byte) (n int,err error)Write(buf []byte) (n int,err error)
}package twotype 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 = file2type Writer interface {Write(buf []byte) (n int err error)
}var file1 two.IStream = new(File)
var file4 Writer = file1var file1 Writer = new(File)
var file5 two.IStream = file1 // 编译不能通过

View Code

    3.5.4 接口查询

var file1 Writer = ...
if file5,ok := file1.(two.IStream); ok {...
}var file1 Writer = ...
if file6,ok := file1.(*File); ok {...
}

View Code

    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 mainimport "fmt"func Add(x,y int) {z := x + yfmt.Println(z)
}func main() {for i:= 0; i < 10 ; i++ {go Add(i,i)}
}

add

  4.4 并发通信

package mainimport "fmt"
import "sync"
import "runtime"var counter int = 0func Count(lock *sync.Mutex) {lock.Lock()counter++fmt.Println(counter)lock.Unlock()
}func main() {lock := &sync.Mutex{}for i := 0; i < 10; i++ {go Count(lock)}for {lock.Lock()c := counterlock.Unlock()runtime.Gosched()if c >= 10 {break}}
}

thread

  4.5 channel

package mainimport "fmt"func Count(ch chan int) {ch <- 1fmt.Println("Counting")
}func main() {chs := make([]chan int,10)for i := 0;i < 10; i++ {chs[i] = make(chan int)go Count(chs[i])}for _,ch := range(chs) {<-ch}
}

channel

    4.5.1 基本语法

var chanName chan ElementTypevar ch chan intvar m map[string]chan boolch := make(chan int)ch <- value // 写入channel
value := <-ch    // 读取channel

View Code

    4.5.2 select

select {case <-chan1:// 如果chan1成功读取数据,则进行该case处理语句case chan2 <- 1:// 如果成功向chan2写入数据,则进行该case处理语句default:// 如果上面都没有成功,则进入default处理流程
}ch := make(chan int,1)for {select {case ch <- 0:case ch <- 1:}i := <-chfmt.Println("Value received:",i)
}

View Code

    4.5.3 缓冲机制

    4.5.4 超时机制

// 首先,我们实现并执行一个匿名的超时等待函数
timeout := make(chan bool,1)go func() {time.Sleep(1e9)    // 等待一秒钟timeout <- true
}()// 然后我们把timeout这个channel利用起来
select {case <-ch:// 从ch中读取到数据case <-timeout:// 一致没有从ch中读取到数据,但从timeout中读取到了数据
}

View Code

    4.5.5 channel的传递

type PipeData struct {value inthandler func(int) intnext chan int
}func handle(queue chan *PipeData) {for data := range queue {data.next <- data.handler(data.value)}
}

View Code

    4.5.6 单向channel

var ch1 chan int
var ch2 chan<- float64
var ch3 <-chan intch4 := make(chan int)
ch5 := <-chan int(ch4)
ch6 := chan<- int(ch4)

View Code

    4.5.7 关闭channel

close(ch)
x,ok := <-ch

View Code

  4.6 多核并行化

type Vector []float64func(v Vector) DoSome(i,n int,u Vector,c chan int) {for ;i < n;i++ {v[i] += u.Op(v[i])}c <- 1
}const NCPU = 16func (v Vector) DoAll(u Vecotr) {c := make(chan int,NCPU)for i := 0;i < NCPU;i++ {go v.DoSome(i*len(v)/NCPU,(i+1)*len(v)/NCPU,u,c)}for i := 0;i < NCPU;i++ {<-c}
}runtime.GOMAXPROCS(16)

View Code

  4.7 出让时间片

  4.8 同步

    4.8.1 同步锁

    4.8.2 全局唯一性操作

var a string
var once sync.Oncefunc setup() {a = "hello,world"
}func dropint() {once.Do(setup)print(a)
}func twoprint() {go doprint()go dropinit()
}

View Code

  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 mainimport ("net""os""bytes""fmt""io"
)func main() {if len(os.Args) != 2 {fmt.Fprintf(os.Stderr,"Usage: %s host:port ",os.Args[0])os.Exit(1)}service := os.Args[1]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(0)
}func checkError(err error) {if err != nil {fmt.Fprintf(os.Stderr,"Fatal error: %s",err.Error())os.Exit(1)}
}func readFully(conn net.Conn) ([]byte,error) {defer conn.Close()result := bytes.NewBuffer(nil)var buf  [512]bytefor {n,err := conn.Read(buf[0:])result.Write(buf[0: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 mainimport ("net""os""fmt""io/ioutil"
)func main() {if len(os.Args) != 2 {fmt.Fprintf(os.Stderr,"Usage: %s host:port ",os.Args[0])os.Exit(1)}service := os.Args[1]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(0)
}func checkError(err error) {if err != nil {fmt.Fprintf(os.Stderr,"Fatal error: %s",err.Error())os.Exit(1)}
}

simplehttp2

  5.2 HTTP编程

    5.2.1 HTTP客户端

package mainimport ("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 stringAuthors []stringPublisher stringIsPublished boolPrice 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}')

View Code

    5.4.2 解码JSON数据

func Unmarshal(data []byte,v interface{}) errorvar book Bookerr := 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)

View Code

    5.4.3 解码未知结构的JSON数据

b := []byte('{"Title":"Go语言编程","Authors":["XuShiwei",HughLv"],"Publisher":"ituring.com.cn","IsPublished":true,"Price":9.99,"Sales":10000}')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,"Sales":10000
}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")}}
}

View Code

    5.4.4 JSON的流式读写

package mainimport ("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 mainimport ("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 mainimport ("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 mainimport ("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(1)}
}

hash2

  6.5 Go语言的哈希函数

  6.6 加密通道

    6.6.1 加密通信流程

    6.6.2 支持HTTPS的Web服务器

package mainimport ("fmt""net/http"
)const SERVER_PORT = 8080
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 mainimport ("net""net/http""time""fmt""crypto/x509""crypto/rand""crypto/rsa""crypto/tls""encoding/pem""errors""io/ioutil"
)const SERVER_PORT = 8080
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 errorconfig.Certificates = make([]tls.Certificate,1)config.Certificates[0],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 = keyx509Cert,err := x509.ParseCertificate(certDERBlock.Bytes)if err != nil {return}if x509Cert.PublicKeyAlgorithm != x509.RSA || x509Cert.PublicKey.(*rsa.PublicKey).N.Cmp(key.PublicKey.N) != 0 {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 mainimport ("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}
return 0,nil
}func
main() { i,_ := Foo(1,2)
fmt.Println("Hello,world",i)}

hello1

$ go fmt hello1.go

package mainimport "fmt"func Foo(a, b int) (ret int, err error) {if a > b {return a, nil} else {return b, nil}return 0, nil
}func main() {i, _ := Foo(1, 2)fmt.Println("Hello,world", i)
}

test2

  7.3 远程import支持

package mainimport ("fmt""github.com/myteam/exp/crc32"
)

View Code

  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 mainimport ("fmt""reflect"
)func main() {var x float64 = 3.4fmt.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 mainimport ("fmt""reflect"
)func main() {var x float64 = 3.4p := 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)
}

View Code

  9.1.3 对结构的反射操作

package mainimport ("fmt""reflect"
)type T struct {A intB string
}func main() {t := T{203,"mh203"}s := reflect.ValueOf(&t).Elem()typeOfT := s.Type()for i := 0; i < s.NumField(); i++ {f := s.Field(i)fmt.Printf("%d: %s %s = %v\n",i,typeOfT.Field(i).Name,f.Type(),f.Interface())}
}

View Code

  9.2 语言交互性

package mainimport "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(100)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 mainimport ("flag""fmt""os""strconv"
)var goal intfunc primeTask(c chan int) {p := <-cif p > goal {os.Exit(0)}fmt.Println(p)nc := make(chan int)go primeTask(nc)for {i := <-cif i%p != 0 {nc <- i}}
}func main() {flag.Parse()args := flag.Args()if args != nil && len(args) > 0 {var err errorgoal,err = strconv.Atoi(args[0])if err != nil {goal = 100}} else {goal = 100}fmt.Println("goal=",goal)c := make(chan int)go primeTask(c)for i := 2;;i++ {c <- i}
}

primes

    9.4.4 任务

    9.4.5 任务调度

    9.4.6 上下文切换

    9.4.7 通信机制

  9.5 接口机理

    9.5.1 类型赋值给接口

package mainimport "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 ISpeakerspeaker = &SimpleSpeaker{"Hell"}speaker.Speak()
}

interface-1

    9.5.2 接口查询

    9.5.3 接口赋值

转载于:https://www.cnblogs.com/revoid/p/9223846.html

Go语言编程 (许式伟 等 著)相关推荐

  1. 许式伟《Go语言编程》章节摘录:Go语言简史

    提起Go语言的出身,我们就必须将我们饱含敬意的眼光投向持续推出惊世骇俗成果的贝尔实验室.贝尔实验室已经走出了多位诺贝尔奖获得者,一些对于现在科技至关重要的研究成果,比如晶体管.通信技术.数码相机的感光 ...

  2. [ ECUG 专题回顾]《再谈 CERL:详论 GO 与 ERLANG 的并发编程模型差异》-许式伟(七牛云存储 CEO)...

    许式伟:我们开始,先介绍一下ECUG,从07年开始,最早在珠三角珠海广州深圳,在珠三角兴起,最早是Erlang的社区.大概到10年的时候更名为实时效云计算的群组,最早的时候也不局限于Erlang,而是 ...

  3. 许式伟:我与Go语言的这十年

    2007 年 9 月 20 日,关于设计一门全新语言的讨论正式开始,这门全新的语言,就是后来的 Go.时至今日,Go 语言已经发布到 1.9 版本,走过了整整十年的历程.在这十年间,Go 语言两夺 T ...

  4. 许式伟:Go 语言有机会登顶,桌面侧亟待突破

    写在前面 许式伟 这是 GVP 首位公布的超级大咖,这是一个所有中国 Gopher 无人不知的名字.无论是创建国内首批全面拥抱 Go 语言的七牛云,还是< Go 语言编程>一书的编写,抑或 ...

  5. 许式伟:我与Go语言的这十年[转]

    2017-12-18 许式伟 Go中国 2007 年 9 月 20 日,关于设计一门全新语言的讨论正式开始,这门全新的语言,就是后来的 Go.时至今日,Go 语言已经发布到 1.9 版本,走过了整整十 ...

  6. 关于 许式伟谈Go Erlang并发编程差异

    写在开头: 这篇文章是ECUG2014年七牛CEO许式伟的演讲稿.这篇文章很详细的分析了Go和 Erlang在实现并发编程的差异,但是有些内容可能因为作者本人个人情感的一些原因有些出入导致了知乎上的一 ...

  7. 我的Go+语言初体验——【三、spx案例测试_许式伟先生推荐补充(附-视频)】

    欢迎大家参与[我的Go+语言初体验]活动: 活动地址:[https://bbs.csdn.net/topics/603464006?utm_source=1594742339] 安装过程博文:[我的G ...

  8. 随想录(学习《许式伟的架构课》)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 市面上关于软件架构的课程大概有这么几种, 1.设计模式类,比如<设计模式>.< ...

  9. 技术人攻略访谈三十八-许式伟:十一年逆流顺流,首席架构师到CEO

    文:Gracia (本文为原创内容,部分或全文转载均需经过作者授权,并保留完整的作者信息和技术人攻略介绍.) 导语:本期访谈对象@许式伟,七牛云存储CEO,国内Go语言圈领军人物,ECUG社区发起人. ...

最新文章

  1. 区块链论文: Bitcoin-NG: A Scalable Blockchain Protocol
  2. 【theano-windows】学习笔记十五——受限玻尔兹曼机
  3. 这篇顶会paper,讲述了疫情期间憋疯的你和我
  4. java文件编译为class文件需要键入什么命令_cmd命令行 编译Java 文件
  5. 浅谈SDN中的OverLay与UnderLay技术
  6. python读hadoop_python读取hdfs并返回dataframe教程
  7. Docker镜像优化:从1.16GB到22.4MB,真强!
  8. HBuilderX里面创建项目时没有模板解决方案
  9. AutoCAD2018_图层编辑
  10. 用python简易制作晋江城小说下载器(GUI+爬虫+多线程)
  11. 【PCL】【PCL实践】【PCL的使用学习记录】
  12. intel和ATT汇编格式区别
  13. Win10重装系统/迁移系统,教你如何简单快速删除原系统文件
  14. html中splice向数组添加元素,js中splice()的强大(删除,插入或替换数组的元素)
  15. Android 面试必备之 JVM 相关口水话,flutterpageview动画
  16. 【解题报告】2017-2018 8th BSUIR Open Programming Contest-C Good subset 线性基+线段树
  17. 安卓导入自定义下载矢量图标
  18. CodeKK源码地址
  19. 如何营造性能至上的团队文化
  20. TCPMP编译方法(转载)

热门文章

  1. 背包问题详解:01背包、完全背包、多重背包
  2. CentOS6 安装中文输入法
  3. 【信息学奥数】—— 第一部分 C++语言 知识总结
  4. 作用域和作用域链详解
  5. 华为一出鸿蒙开 鲲鹏展翅九万里,科技 _ 不止“鸿蒙”,还有子龙、浩天、青鸟、朱雀……华为简直注册了整本《山海经》!中国人有多浪漫,看这些名字就知道了...
  6. 【闲聊杂谈】一篇给你讲清楚JVM调优的本质
  7. 系统架构设计师从意气风发地报考到最终无奈的放弃
  8. 2022-2027年中国科技园行业市场全景评估及发展战略规划报告
  9. 华为服务器将采用深度国产操作系统,华为与深度系统达成合作,将打造属于国人自己的操作系统!...
  10. 创新研报 | 如何激发中国半导体企业发展潜力从而获得竞争优势,领跑新一轮增长?