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 := 0
    for _,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,<-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{"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 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
    if 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 simplemath

func Add(a int,b int) int {
    return a + b
}
add
package simplemath

import "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 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(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) int

var (
    v1 int
    v2 string
)
varTest1

    2.1.2 变量初始化

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

    2.1.3 变量赋值

var v10 int
v10 = 123

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

    2.2.3 预定义常量

const (
    c0 = iota
    c1 = iota
    c2 = iota
)

const (
    a = 1 << iota
    b = 1 << iota
    c = 1 << iota
)

const (
    u = iota * 42
    v float64 = iota * 42
    w = iota * 42
)

const x = iota
const y = iota

const (
    c0 = iota
    c1
    c2
)

const (
    a = 1 << 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
}
View Code

    2.3.4 复数类型

    2.3.5 字符串

package main

import "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 main

import "fmt"

func Modify(array [5]int) {
    array[0] = 10
    fmt.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 main

import "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 main

import "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 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["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:
        fallthrough
    case 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 := 0
    HERE:
        fmt.Println(i)
    i++
    if i < 10 {
        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 v1 int = 1
    var v2 int64 = 234
    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() {
    var j int = 5
    a := func()(func()) {
        var i int = 10
        return func() {
            fmt.Printf("i,j:%d,%d\n",i,j)
        }
    }()
    
    a()
    
    j *= 2
    
    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() {
    var a Integer = 1
    if 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() 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)
View Code

    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 // 编译不能通过
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 main

import "fmt"

func Add(x,y int) {
    z := x + y
    fmt.Println(z)
}

func main() {
    for i:= 0; i < 10 ; i++ {
        go Add(i,i)
    }
}
add

  4.4 并发通信

package main

import "fmt"
import "sync"
import "runtime"

var counter int = 0

func 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 := counter
        
        lock.Unlock()
        
        runtime.Gosched()
        
        if c >= 10 {
            break
        }
    }
}
thread

  4.5 channel

package main

import "fmt"

func Count(ch chan int) {
    ch <- 1
    fmt.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 ElementType

var ch chan int

var m map[string]chan bool

ch := 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 := <-ch
    fmt.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 int
    handler func(int) int
    next 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 int

ch4 := 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 []float64

func(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 = 16

func (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.Once

func 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 main

import (
    "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]byte
    for {
        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 main

import (
    "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 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
    }')
View Code

    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)
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 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(1)
    }
}
hash2

  6.5 Go语言的哈希函数

  6.6 加密通道

    6.6.1 加密通信流程

    6.6.2 支持HTTPS的Web服务器

package main

import (
    "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 main

import (
    "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 error
    config.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 = key
    
    x509Cert,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 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
    }
return 0,nil
}

func
main() { i,_ := Foo(1,2)
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
    }
    return 0, nil
}

func main() {
    i, _ := Foo(1, 2)
    fmt.Println("Hello,world", i)
}
test2

  7.3 远程import支持

package main

import (
    "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 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)
}
View Code

  9.1.3 对结构的反射操作

package main

import (
    "fmt"
    "reflect"
)

type T struct {
    A int
    B 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 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(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 main

import (
    "flag"
    "fmt"
    "os"
    "strconv"
)

var goal int

func primeTask(c chan int) {
    p := <-c
    
    if p > goal {
        os.Exit(0)
    }
    
    fmt.Println(p)
    
    nc := make(chan int)
    
    go primeTask(nc)
    
    for {
        i := <-c
        
        if i%p != 0 {
            nc <- i
        }
    }
}

func main() {
    flag.Parse()
    
    args := flag.Args()
    
    if args != nil && len(args) > 0 {
        var err error
        goal,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 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 接口赋值

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值