Happy Go Part II
Yo-An Lin (c9s)
c9s@twitter.com
c9s@github.com
Intro
•

was the GitHub Top 1
Contributor ( http://git.io/top )

•

3+ years Perl/VimL
programming

•

3+ years PHP progra...
Go?
Ken Thompson
Rob Pike
Started since 2007
Announced in
November 2009
Used in some of Google’s
production system
What’s Go
•

Statically-Typed Language 靜態型別編譯語⾔言

•

Built-in Concurrency 內建並發性⽀支持

•

Statically-linked Native Binary 靜態連...
About The Language
•

Concise variable declaration 簡潔的變數定義

•

Type Inference 型別推導

•

Easy to use 簡易使⽤用

•

Composition i...
About The Tools
•

語⾔言規格的修改,可透過 go fix 來將舊版語法或程式碼做⾃自
動修正

•

編碼⾵風格可透過 go fmt 來統⼀一所有格式,以及⾃自動去除空
⽩白⾏行、換⾏行、縮排等等。 且可以⽤用 grammar...
What’s the difference?
那麼有什麼不同呢?
Interpreted language
Statically compiled
language
Statically-typed (or
compiled) languages are
usually faster
Benchmark
•

Faster than Node.js, Python, Perl, PHP, Ruby
(without C/C++ extensions)

•

A bit slower than C, C++ and Java...
Benchmark
http://www.techempower.com/benchmarks/
and it compiles fast
But it costs a lot of time
But it costs a lot of time
Go solves this
problem
Concurrency?
Prefork
Prefork
Prefork
Prefork
•

Hard to share data between processes.

•

Costs a lot of CPU cycle.

•

Copying process is time consuming.

•

...
Just use Go Routine
Just use Go Routine

All in one process
Just use Go Routine
•

Threaded worker pool

•

use pipeline (channel) to communicate

•

CSP (Communicating Sequential Pr...
Easier Deployment
Deployment Pain
•

Install required packages

•

Install application package dependencies

•

(dependency hell)

•

(incom...
You can just build &
scp
And it works
Q & A Time
————————
Ready For
Production?
Companies using Go
•

Google

•

Carbon Games

•

Sound Cloud

•

Iron.io

•

BCC

•

SmugMug

•

Canonical

•

Bitly

•

...
Enough Open
Sourced Packages?
15,298 packages
http://godoc.org/-/index
Is it popular?
Supported OS?
Supported OS
•

Linux

•

BSD, OpenBSD

•

Windows

•

Mac OS

•

Plan 9
Architectures?
Architectures
•

i386

•

amd64

•

arm
Development
Environment
For Go
Go IDE
•

Sublime Text 2

•

IntelliJ

•

LiteIDE

•

Intype

•

NetBeans

•

Eclipse

•

Zeus

http://geekmonkey.org/arti...
go/misc
•

misc/vim : generic vim plugin

•

misc/emacs : emacs go mode

•

misc/git : pre-commit hook (run go fmt before ...
vim: gocode

•

go completion daemon

•

vim omni completion support

•

scan code from $GOPATH
Go Environment
•

$GOROOT ( defaults to /usr/local/go )

•

$GOPATH ( your packages )

•

$GOARCH

•

$GOOS
$GOPATH
mkdir ~/go
export GOPATH=~/go

執⾏行 go get 時,packages 會安裝到
GOPATH 第⼀一個 path 內
$GOPATH
mkdir ~/go/vendor
mkdir ~/go/private
export GOPATH=~/go/vendor:~/go/private

可利⽤用 $GOPATH 將私⽤用 package 分開
$GOPATH
mkdir ~/go
export GOPATH=~/go

path

description

~/go/src

your source code

~/go/pkg

compiled packages (*.a)

~...
Hello World
$ vim hello.go
package main
!

import "fmt"
!

func main() {
fmt.Printf("hello, worldn")
}
Hello World
$ go run hello.go

$ go build -o hello hello.go
$ ./hello
Go commands
編譯後執⾏行程式 (必須是 main package)

•

go run

•

go build 編譯

•

go install 編譯並且安裝

•

go get 抓取遠端套件並且編譯安裝
Basic Application
Basic Application
package main	
!

import "fmt"	
!

func main() {	
	 fmt.Println("anything here")	
}
Basic commands
•

go build app.go

go build -x app.go

•

go run app.go

go run -x app.go

•

go install
Types
Types
•

int, int8, int16, int32, int64,

•

float32, float64

•

string

•

byte
Basic Type Conversion
	 var a int32 = 32	
	 var b int64 = int64(a)	
	 var c int = int(a)
Basic Type Conversion
	 var str = "Hello World"	
	 var data []byte = []byte(str)	
	 fmt.Println(data)
Basic Type Conversion
	 var str = "Hello World"	
	 var data []byte = []byte(str)	
	 fmt.Println(data)

[72 101 108 108 111...
Slice & Array
Slice & Array Type

•

Array: [10]int, [3]int

•

Slice: []int, []string, []byte
Slice & Array
Array:


•




list := […]int{1,2,3,4,5 }

list := [5]int{ 1,2,3,4,5 }
Slice:


•




list := []int{ 1, 2, 3...
Slice & Array
Array:


•




var list = […]int{1,2,3,4,5 }

var list = [5]int{ 1,2,3,4,5 }
Slice:


•




var list = []int...
Slice & Array
Array:


•




var list [5]int = […]int{1,2,3,4,5 }

var list [5]int = [5]int{ 1,2,3,4,5 }
Slice:


•




va...
Slice 切⽚片
Slice - appending
	 names := []string{"Mary", "Lily", "July"}	
	 names = append(names, "Jane")
Slice - iterating
	 names := []string{“Mary","Lily","July"}	
!

	 for i, name := range names {	
	 	 fmt.Println(i, name)	
...
String = Slice of byte
a string is in effect a read-only slice of bytes
Slice - string
•

string is basically a slice of byte.

•

slice is immutable, string is also immutable.

•

which means: ...
Slice - string
	 var str = "abcdefg"	
	 fmt.Printf("str[0] = byte: %#vn", str[0])	
	 fmt.Printf("str[2:5] = []byte: %#vn",...
Slice - string
	
	
	
	

var str = "abcdefg"	
for i, c := range str {	
	 fmt.Printf("str[%d] = %cn", i, c)	
}

str[0]
str[1...
More about string
http://blog.golang.org/strings
Slice - internals
Slice internals: slice header

[]byte{ 60, 61, 62, 63, 64 }
Slice internal: slice header
	
	
	
	
	

// this creates a slice with header:	
//
start from 0	
//
length = 7	
//
data = po...
Slice internal: slice header
// we get a copy of slice header	
func addOne(list []int) {	
	 for i, _ := range list {	
	 	 ...
Slice - internals
x := [3]string{"Лайка", "Белка", "Стрелка"}	
s := x[:] // a slice referencing the storage of x
Slice - internals
x := [3]string{"Лайка", "Белка", "Стрелка"}	
s := x[:] // a slice referencing the storage of x
Slice - internals
x := [3]string{"Лайка", "Белка", "Стрелка"}	
s := x[:] // a slice referencing the storage of x
Slice - internals
s = s[2:4]
Slice - internals
s = s[2:4]
Slice - internals
s = s[2:4]

Slicing does not copy the slice's data. It creates a new
slice header that points to the ori...
Slice - internals
s = s[:cap(s)]
Slice - internals
s = s[:cap(s)]
More About Slice
http://blog.golang.org/slices
http://blog.golang.org/go-slices-usage-and-internals
Map
Map
contacts := map[string]string {}
Type of Key
Map
contacts := map[string]string {}
Type of Value
Map
contacts := map[string]string {}
contacts := map[string]string {	
	 "Jack": "02-2345678",	
}
Map
contacts := map[string]string {}
contacts := map[string]string {	
	 "Jack": "02-2345678",	
}	
Initialised Key

Initial...
Map
contacts := map[string]string {}
contacts := map[string]string {	
	 "Jack": "02-2345678",	
}	
“,” Composite Literal Sy...
Map
contacts := map[string]string {}
contacts := map[string]string {	
	 "Jack": “02-2345678",	
	 "Lisa": "1234567890",	
}	...
Map
var contacts map[string]string 	
= map[string]string {	
	 “Jack”: "02-2345678",	
}
Map - assign
	 contacts := map[string]string{}	
!

	 contacts["key"] = "value"
Map - defined
	 contacts := map[string]string{}	
!

	 if _, ok := contacts["key"]; ok {	
!

	 }	

Multiple Return Value
Map - defined
	 contacts := map[string]string{}	
!

	 if _, ok := contacts["key"]; ok {	
!

	 }	

Variable Assignment
Map - defined
	 contacts := map[string]string{}	
!

	 if _, ok := contacts["key"]; ok {	
!

	 }	

boolean context
Map - defined
	 contacts := map[string]string{}	
!

	 if _, ok := contacts["key"]; ok {	
!

	 }	

boolean: if found
Map - defined
	 contacts := map[string]string{}	
!

	 if _, ok := contacts["key"]; ok {	
!

	 }	

actual value with the defi...
Map - defined
	 if val, ok := contacts["key"]; ok {	
	 	 _ = val	
	 }	
Unused Variable
Map - delete

Built-in Function

	 contacts := map[string]string{}	
	 contacts["key"] = "value"	
	 delete(contacts, “key")
Map - iterating
	 contacts["key"] = "value"	
	 contacts["key2"] = “value2"	
!

	
	
	
	

for key, val := range contacts {	
...
Pointer & Reference
Pointer
•

pointer is basically like we used in C.

•

easy to use but safer than C.

•

no segmentation-fault.!

•

compi...
Pointer: new & make

•

new() - doesn’t initialise value. zero-ed memory
allocation.!

•

make() - allocation with data in...
Pointer
	 a := new(int)	
	 fmt.Println(a)	
	 fmt.Println(*a)
Pointer
	 a := new(int)	
	 fmt.Println(a)	
	 fmt.Println(*a)

0x2101ef018	
0
Reference
	
	
	
	

var a int = 10	
var b *int = &a	
a = 12	
fmt.Println(a, *b)	

12 12
Struct
Struct

•

similar to the struct we used in C.

•

but you can embed another struct in your struct. so
called “embedded st...
Struct
type Contact struct {	
	 Name string	
	 Phone string	
}
Struct
type Contact struct {	
	 Name string	
	 Phone string	
}	
The type name
Struct
type Contact struct {	
	 Name string	
	 Phone string	
}	
The type of “Contact “ is a struct
Struct
type Contact struct {	
	 Name string	
	 Phone string	
}	
Struct Field Name
Struct
type Contact struct {	
	 Name string	
	 Phone string	
}	
Field Type
Struct Allocation
func main() {	
	 p1 := Contact{Name: "Lisa", Phone: "1234"}	
	 p2 := Contact{"Mary", "2345"}	
	 fmt.Prin...
Composite Literal

a := [...]string
{Enone: "no error", Eio: "Eio", Einval: "invalid argument"}	
s := []string
{Enone: "no...
Struct Allocation
	 p1 := Contact{Name: "Lisa", Phone: "1234"}

…Equals To…
	 p1 := Contact{"Lisa", "1234"}
Struct Allocation
new(File)	
&File{}

The expressions new(File) and &File{} are equivalent.
Accessing Struct Fields
contact1 := Contact{"Mary", "12345678"}	
fmt.Println(contact1.Name)
Use “.” to access struct field
Accessing Struct Fields
contact1 := Contact{"Mary", "12345678"}	
fmt.Println(contact1.Name)
Allocate a struct and return t...
Accessing Struct Fields
contact1 := Contact{"Mary", "12345678"}	
fmt.Println(contact1.Name)
Pointer of type Contact

conta...
Accessing Struct Fields
contact1 := Contact{"Mary", "12345678"}	
fmt.Println(contact1.Name)

contact2 := &Contact{"Mary", ...
Custom Type
Custom Types
type Score int	
type ScoreMap map[string]int	
type NickName string
Custom Types
type Score int	
type ScoreMap map[string]int	
type NickName string

type Score is a int type
Custom Types
type Score int	
!

func CalculateScore(a Score, b Score) Score {	
	 return a + b	
}
Strict type of your data ...
Custom Types
type Score int	
!

func CalculateScore(a Score, b Score) Score {	
	 return a + b	
}
Strict type of your data ...
Custom Types
type Score int	
!

func CalculateScore(a Score, b Score) Score {	
	 return a + b	
}
Strict type of your data ...
Type Methods
type NickName string	
!

func (self NickName) Say() {	
	 fmt.Println(self)	
}
Type Methods
type NickName string	
!

func (self NickName) Say() {	
	 fmt.Println(self)	
}	
Receiver
Type Methods
type NickName string	
!

func (self * NickName) Say() {	
	 fmt.Println(self)	
}	
You may also use the referen...
Type Methods
a := NickName("foo")	
a.Say()
Allocate a string
Type Methods
a := NickName("foo")	
a.Say()
Type cast to NickName
Type Methods
a := NickName("foo")	
a.Say()
b := &a	
b.Say()
Type Methods
a := NickName("foo")	
a.Say()
b := &a	
b.Say()
Always use “.” to access fields or methods .
Interface
Interface
•

interface defines the requirement of the object
method prototype.

•

you define the requirement and check the
...
interface
type Worker interface {	
	 Work()	
}
interface
type Worker interface {	
	 Work()	
}	
type SeedWorker struct{}	
!

func (self *SeedWorker) Work() {	
	 // work.....
interface
// accept anything implements 	
// the interface of Worker	
func HandleData(worker Worker) {	
	 worker.Work()	
}...
interface{}
•

interface{} is basically a universal pointer.

•

just like “id” we used in Objective-C

•

just like the v...
interface{}
Given Struct Foo and Bar
type Foo struct{}	
type Bar struct{}
interface{}
Given Struct Foo and Bar
type Foo struct{}	
type Bar struct{}
	
	
	
	
	

var
var
var
b =
a =

a interface{} = ...
interface{}
type anything interface{}
var a anything = Foo{}	
var b anything = &Foo{}	
var c anything = &Bar{}
interface{}
type anything interface{}	
func AcceptAnything(a anything) {	
	 // do something	
}	
func main() {	
	 AcceptAny...
Building Web
Applications
Using net/http
Data Structure For Page
$ mkdir wiki	
$ cd wiki	
$ vim page.go
Data Structure For Page
package main	
!

import (	
	 "fmt"	
	 "io/ioutil"	
)
Data Structure For Page
type Page struct {	
	 Title string	
	 Body []byte	
}
Data Structure For Page
type Page struct {	
	 Title string	
	 Body []byte	
}	

func (p *Page) save() error {	
	 filename :...
Data Structure For Page
func loadPage(title string) (*Page, error) {	
	 filename := title + ".txt"	
	 body, err := ioutil....
Build it!
$ go build wiki.go
Build it!
$ go build wiki.go	
$ ./wiki	
This is a sample page.
Introducing net/http
package main	
!

import (	
	 "fmt"	
	 "net/http"	
)
Introducing net/http
Type of Handler

func handler(w http.ResponseWriter, r *http.Request) {	
	 fmt.Fprintf(w, "Hi there, ...
Introducing net/http
Resource handle which implements Writer interface.

func handler(w http.ResponseWriter, r *http.Reque...
Introducing net/http
func handler(w http.ResponseWriter, r *http.Request) {	
	 fmt.Fprintf(w, "Hi there, I love %s!", r.UR...
Introducing net/http
func handler(w http.ResponseWriter, r *http.Request) {	
	 fmt.Fprintf(w, "Hi there, I love %s!", r.UR...
Introducing net/http
func handler(w http.ResponseWriter, r *http.Request) {	
	 fmt.Fprintf(w, "Hi there, I love %s!", r.UR...
Introducing net/http
http://localhost:8080/monkeys

Hi there, I love monkeys!
Using net/http
package main	
!

import (	
	 "fmt"	
	 "io/ioutil"	
	 "net/http"	
)	
Import http package.
Using net/http
func viewHandler(w http.ResponseWriter, r *http.Request) {	
	 title := r.URL.Path[len("/view/"):]	
	 p, _ :...
Using net/http
func viewHandler(w http.ResponseWriter, r *http.Request) {	
	 title := r.URL.Path[len("/view/"):]	
	 p, _ :...
Using net/http
func viewHandler(w http.ResponseWriter, r *http.Request) {	
	 title := r.URL.Path[len("/view/"):]	
	 p, _ :...
Using net/http
func main() {	
	 http.HandleFunc("/view/", viewHandler)	
	 http.ListenAndServe(":8080", nil)	
}
Build it!
$ go build wiki.go
Build it!
$
$
$
$

vim test.txt	
go build wiki.go	
./wiki	
curl http://localhost:8080/view/test
Edit handler
func editHandler(w http.ResponseWriter, r *http.Request) {	
	 title := r.URL.Path[len("/edit/"):]	
	 p, err :...
The html/template package
package main	
!

import (	
	 "html/template"	
	 "io/ioutil"	
	 "net/http"	
)
The html/template package
func editHandler(w http.ResponseWriter, r *http.Request) {	
	 title := r.URL.Path[len("/edit/"):...
The html/template package
<h1>Editing {{.Title}}</h1>	
!
<form action="/save/{{.Title}}" method="POST">	
<div><textarea na...
Save handler
func saveHandler(w http.ResponseWriter, r *http.Request) {	
title := r.URL.Path[len("/save/"):]	
body := r.Fo...
Happy Go Programming
Happy Go Programming
Upcoming SlideShare
Loading in...5
×

Happy Go Programming

4,082

Published on

golang, go, programming, web applications.

Happy Go Programming

  1. 1. Happy Go Part II Yo-An Lin (c9s) c9s@twitter.com c9s@github.com
  2. 2. Intro • was the GitHub Top 1 Contributor ( http://git.io/top ) • 3+ years Perl/VimL programming • 3+ years PHP programming • 2+ years Go programming
  3. 3. Go?
  4. 4. Ken Thompson Rob Pike
  5. 5. Started since 2007
  6. 6. Announced in November 2009
  7. 7. Used in some of Google’s production system
  8. 8. What’s Go • Statically-Typed Language 靜態型別編譯語⾔言 • Built-in Concurrency 內建並發性⽀支持 • Statically-linked Native Binary 靜態連結原⽣生⼆二進位執⾏行檔 • Fast compilation times 極快速的編譯 • Remote package management 內建外部套件管理 • Garbage Collection 使⽤用垃圾收集器 • Safety 安全 (race conditions, type and memory safety for multithreaded program)
  9. 9. About The Language • Concise variable declaration 簡潔的變數定義 • Type Inference 型別推導 • Easy to use 簡易使⽤用 • Composition instead of Inheritance. • Use Interface 使⽤用介⾯面取代 is-a 繼承 • multiple return value 多回傳值函數
  10. 10. About The Tools • 語⾔言規格的修改,可透過 go fix 來將舊版語法或程式碼做⾃自 動修正 • 編碼⾵風格可透過 go fmt 來統⼀一所有格式,以及⾃自動去除空 ⽩白⾏行、換⾏行、縮排等等。 且可以⽤用 grammar 的⽅方式來描述 語法。 • 內建 profiling tools 且⽀支持 Goole pprof ,可直接在 http server 上開 profiler API,利⽤用命令列⼯工具遠端取得 CPU, Memory 使⽤用狀況並進⾏行分析,或產⽣生 call graph 等等資 料。 • 遠端套件可直接透過 go get 安裝
  11. 11. What’s the difference? 那麼有什麼不同呢?
  12. 12. Interpreted language
  13. 13. Statically compiled language
  14. 14. Statically-typed (or compiled) languages are usually faster
  15. 15. Benchmark • Faster than Node.js, Python, Perl, PHP, Ruby (without C/C++ extensions) • A bit slower than C, C++ and Java (sometimes faster than Java) • Low memory footprint (10+ times lower than Java)
  16. 16. Benchmark http://www.techempower.com/benchmarks/
  17. 17. and it compiles fast
  18. 18. But it costs a lot of time
  19. 19. But it costs a lot of time
  20. 20. Go solves this problem
  21. 21. Concurrency?
  22. 22. Prefork
  23. 23. Prefork
  24. 24. Prefork
  25. 25. Prefork • Hard to share data between processes. • Costs a lot of CPU cycle. • Copying process is time consuming. • Waste a lot of memory.
  26. 26. Just use Go Routine
  27. 27. Just use Go Routine All in one process
  28. 28. Just use Go Routine • Threaded worker pool • use pipeline (channel) to communicate • CSP (Communicating Sequential Processes) http://golang.org/doc/faq
  29. 29. Easier Deployment
  30. 30. Deployment Pain • Install required packages • Install application package dependencies • (dependency hell) • (incompatible version hell) • (10 hours later…) • ok, finally onlined.
  31. 31. You can just build & scp
  32. 32. And it works
  33. 33. Q & A Time
  34. 34. ————————
  35. 35. Ready For Production?
  36. 36. Companies using Go • Google • Carbon Games • Sound Cloud • Iron.io • BCC • SmugMug • Canonical • Bitly • Heroku • CloudFlare
  37. 37. Enough Open Sourced Packages?
  38. 38. 15,298 packages http://godoc.org/-/index
  39. 39. Is it popular?
  40. 40. Supported OS?
  41. 41. Supported OS • Linux • BSD, OpenBSD • Windows • Mac OS • Plan 9
  42. 42. Architectures?
  43. 43. Architectures • i386 • amd64 • arm
  44. 44. Development Environment For Go
  45. 45. Go IDE • Sublime Text 2 • IntelliJ • LiteIDE • Intype • NetBeans • Eclipse • Zeus http://geekmonkey.org/articles/20-comparison-of-ides-forgoogle-go
  46. 46. go/misc • misc/vim : generic vim plugin • misc/emacs : emacs go mode • misc/git : pre-commit hook (run go fmt before commmit) • misc/bash : bash completion • zsh/go : zsh completion • misc/cgo : cgo examples
  47. 47. vim: gocode • go completion daemon • vim omni completion support • scan code from $GOPATH
  48. 48. Go Environment • $GOROOT ( defaults to /usr/local/go ) • $GOPATH ( your packages ) • $GOARCH • $GOOS
  49. 49. $GOPATH mkdir ~/go export GOPATH=~/go 執⾏行 go get 時,packages 會安裝到 GOPATH 第⼀一個 path 內
  50. 50. $GOPATH mkdir ~/go/vendor mkdir ~/go/private export GOPATH=~/go/vendor:~/go/private 可利⽤用 $GOPATH 將私⽤用 package 分開
  51. 51. $GOPATH mkdir ~/go export GOPATH=~/go path description ~/go/src your source code ~/go/pkg compiled packages (*.a) ~/go/bin command-line binary
  52. 52. Hello World $ vim hello.go package main ! import "fmt" ! func main() { fmt.Printf("hello, worldn") }
  53. 53. Hello World $ go run hello.go $ go build -o hello hello.go $ ./hello
  54. 54. Go commands 編譯後執⾏行程式 (必須是 main package) • go run • go build 編譯 • go install 編譯並且安裝 • go get 抓取遠端套件並且編譯安裝
  55. 55. Basic Application
  56. 56. Basic Application package main ! import "fmt" ! func main() { fmt.Println("anything here") }
  57. 57. Basic commands • go build app.go
 go build -x app.go • go run app.go
 go run -x app.go • go install
  58. 58. Types
  59. 59. Types • int, int8, int16, int32, int64, • float32, float64 • string • byte
  60. 60. Basic Type Conversion var a int32 = 32 var b int64 = int64(a) var c int = int(a)
  61. 61. Basic Type Conversion var str = "Hello World" var data []byte = []byte(str) fmt.Println(data)
  62. 62. Basic Type Conversion var str = "Hello World" var data []byte = []byte(str) fmt.Println(data) [72 101 108 108 111 32 87 111 114 108 100]
  63. 63. Slice & Array
  64. 64. Slice & Array Type • Array: [10]int, [3]int • Slice: []int, []string, []byte
  65. 65. Slice & Array Array:
 • 
 list := […]int{1,2,3,4,5 }
 list := [5]int{ 1,2,3,4,5 } Slice:
 • 
 list := []int{ 1, 2, 3 }
 list := []string{ “foo”, “bar”, “zoo” }
  66. 66. Slice & Array Array:
 • 
 var list = […]int{1,2,3,4,5 }
 var list = [5]int{ 1,2,3,4,5 } Slice:
 • 
 var list = []int{ 1, 2, 3 }
 var list = []string{ “foo”, “bar”, “zoo” }
  67. 67. Slice & Array Array:
 • 
 var list [5]int = […]int{1,2,3,4,5 }
 var list [5]int = [5]int{ 1,2,3,4,5 } Slice:
 • 
 var list []int = []int{ 1, 2, 3 }
 var list []string = []string{ “foo”, “bar”, “zoo” }
  68. 68. Slice 切⽚片
  69. 69. Slice - appending names := []string{"Mary", "Lily", "July"} names = append(names, "Jane")
  70. 70. Slice - iterating names := []string{“Mary","Lily","July"} ! for i, name := range names { fmt.Println(i, name) }
  71. 71. String = Slice of byte a string is in effect a read-only slice of bytes
  72. 72. Slice - string • string is basically a slice of byte. • slice is immutable, string is also immutable. • which means: “no delete or insert in specific position” • but you can create a new slice references to another slice with position and length.
  73. 73. Slice - string var str = "abcdefg" fmt.Printf("str[0] = byte: %#vn", str[0]) fmt.Printf("str[2:5] = []byte: %#vn", str[2:5]) str[0] = byte: 0x61 str[2:5] = []byte: "cde"
  74. 74. Slice - string var str = "abcdefg" for i, c := range str { fmt.Printf("str[%d] = %cn", i, c) } str[0] str[1] str[2] str[3] str[4] str[5] str[6] = = = = = = = a b c d e f g
  75. 75. More about string http://blog.golang.org/strings
  76. 76. Slice - internals
  77. 77. Slice internals: slice header []byte{ 60, 61, 62, 63, 64 }
  78. 78. Slice internal: slice header // this creates a slice with header: // start from 0 // length = 7 // data = pointer to the int array. foo := []int{0, 1, 2, 3, 4, 5, 6} ! // this copy the slice header to the function addOne(foo)
  79. 79. Slice internal: slice header // we get a copy of slice header func addOne(list []int) { for i, _ := range list { // this modify the actual data // through the data pointer. list[i]++ } }
  80. 80. Slice - internals x := [3]string{"Лайка", "Белка", "Стрелка"} s := x[:] // a slice referencing the storage of x
  81. 81. Slice - internals x := [3]string{"Лайка", "Белка", "Стрелка"} s := x[:] // a slice referencing the storage of x
  82. 82. Slice - internals x := [3]string{"Лайка", "Белка", "Стрелка"} s := x[:] // a slice referencing the storage of x
  83. 83. Slice - internals s = s[2:4]
  84. 84. Slice - internals s = s[2:4]
  85. 85. Slice - internals s = s[2:4] Slicing does not copy the slice's data. It creates a new slice header that points to the original array.
  86. 86. Slice - internals s = s[:cap(s)]
  87. 87. Slice - internals s = s[:cap(s)]
  88. 88. More About Slice http://blog.golang.org/slices http://blog.golang.org/go-slices-usage-and-internals
  89. 89. Map
  90. 90. Map contacts := map[string]string {} Type of Key
  91. 91. Map contacts := map[string]string {} Type of Value
  92. 92. Map contacts := map[string]string {} contacts := map[string]string { "Jack": "02-2345678", }
  93. 93. Map contacts := map[string]string {} contacts := map[string]string { "Jack": "02-2345678", } Initialised Key Initialised Value
  94. 94. Map contacts := map[string]string {} contacts := map[string]string { "Jack": "02-2345678", } “,” Composite Literal Syntax
  95. 95. Map contacts := map[string]string {} contacts := map[string]string { "Jack": “02-2345678", "Lisa": "1234567890", } “,” Composite Literal Syntax
  96. 96. Map var contacts map[string]string = map[string]string { “Jack”: "02-2345678", }
  97. 97. Map - assign contacts := map[string]string{} ! contacts["key"] = "value"
  98. 98. Map - defined contacts := map[string]string{} ! if _, ok := contacts["key"]; ok { ! } Multiple Return Value
  99. 99. Map - defined contacts := map[string]string{} ! if _, ok := contacts["key"]; ok { ! } Variable Assignment
  100. 100. Map - defined contacts := map[string]string{} ! if _, ok := contacts["key"]; ok { ! } boolean context
  101. 101. Map - defined contacts := map[string]string{} ! if _, ok := contacts["key"]; ok { ! } boolean: if found
  102. 102. Map - defined contacts := map[string]string{} ! if _, ok := contacts["key"]; ok { ! } actual value with the defined type
  103. 103. Map - defined if val, ok := contacts["key"]; ok { _ = val } Unused Variable
  104. 104. Map - delete Built-in Function contacts := map[string]string{} contacts["key"] = "value" delete(contacts, “key")
  105. 105. Map - iterating contacts["key"] = "value" contacts["key2"] = “value2" ! for key, val := range contacts { _ = key _ = val }
  106. 106. Pointer & Reference
  107. 107. Pointer • pointer is basically like we used in C. • easy to use but safer than C. • no segmentation-fault.! • compile-time type checking.
  108. 108. Pointer: new & make • new() - doesn’t initialise value. zero-ed memory allocation.! • make() - allocation with data initialisation.
  109. 109. Pointer a := new(int) fmt.Println(a) fmt.Println(*a)
  110. 110. Pointer a := new(int) fmt.Println(a) fmt.Println(*a) 0x2101ef018 0
  111. 111. Reference var a int = 10 var b *int = &a a = 12 fmt.Println(a, *b) 12 12
  112. 112. Struct
  113. 113. Struct • similar to the struct we used in C. • but you can embed another struct in your struct. so called “embedded struct”
  114. 114. Struct type Contact struct { Name string Phone string }
  115. 115. Struct type Contact struct { Name string Phone string } The type name
  116. 116. Struct type Contact struct { Name string Phone string } The type of “Contact “ is a struct
  117. 117. Struct type Contact struct { Name string Phone string } Struct Field Name
  118. 118. Struct type Contact struct { Name string Phone string } Field Type
  119. 119. Struct Allocation func main() { p1 := Contact{Name: "Lisa", Phone: "1234"} p2 := Contact{"Mary", "2345"} fmt.Println(p1, p2) }
  120. 120. Composite Literal a := [...]string {Enone: "no error", Eio: "Eio", Einval: "invalid argument"} s := []string {Enone: "no error", Eio: "Eio", Einval: "invalid argument"} m := map[int]string{Enone: "no error", Eio: "Eio", Einval: "invalid argument"}
  121. 121. Struct Allocation p1 := Contact{Name: "Lisa", Phone: "1234"} …Equals To… p1 := Contact{"Lisa", "1234"}
  122. 122. Struct Allocation new(File) &File{} The expressions new(File) and &File{} are equivalent.
  123. 123. Accessing Struct Fields contact1 := Contact{"Mary", "12345678"} fmt.Println(contact1.Name) Use “.” to access struct field
  124. 124. Accessing Struct Fields contact1 := Contact{"Mary", "12345678"} fmt.Println(contact1.Name) Allocate a struct and return the reference contact2 := &Contact{"Mary", "12345678"} fmt.Println(contact1.Name)
  125. 125. Accessing Struct Fields contact1 := Contact{"Mary", "12345678"} fmt.Println(contact1.Name) Pointer of type Contact contact2 := &Contact{"Mary", "12345678"} fmt.Println(contact1.Name)
  126. 126. Accessing Struct Fields contact1 := Contact{"Mary", "12345678"} fmt.Println(contact1.Name) contact2 := &Contact{"Mary", "12345678"} fmt.Println(contact2.Name) Always use “.” to access struct field
  127. 127. Custom Type
  128. 128. Custom Types type Score int type ScoreMap map[string]int type NickName string
  129. 129. Custom Types type Score int type ScoreMap map[string]int type NickName string type Score is a int type
  130. 130. Custom Types type Score int ! func CalculateScore(a Score, b Score) Score { return a + b } Strict type of your data makes your application safer.
  131. 131. Custom Types type Score int ! func CalculateScore(a Score, b Score) Score { return a + b } Strict type of your data makes your application safer. CalculateScore( 20 ) Compilation Fail
  132. 132. Custom Types type Score int ! func CalculateScore(a Score, b Score) Score { return a + b } Strict type of your data makes your application safer. CalculateScore( 20 ) Compilation Fail CalculateScore( Score(20) ) Compilation Pass
  133. 133. Type Methods type NickName string ! func (self NickName) Say() { fmt.Println(self) }
  134. 134. Type Methods type NickName string ! func (self NickName) Say() { fmt.Println(self) } Receiver
  135. 135. Type Methods type NickName string ! func (self * NickName) Say() { fmt.Println(self) } You may also use the reference. (faster)
  136. 136. Type Methods a := NickName("foo") a.Say() Allocate a string
  137. 137. Type Methods a := NickName("foo") a.Say() Type cast to NickName
  138. 138. Type Methods a := NickName("foo") a.Say() b := &a b.Say()
  139. 139. Type Methods a := NickName("foo") a.Say() b := &a b.Say() Always use “.” to access fields or methods .
  140. 140. Interface
  141. 141. Interface • interface defines the requirement of the object method prototype. • you define the requirement and check the requirement in both compile-time and runtime.
  142. 142. interface type Worker interface { Work() }
  143. 143. interface type Worker interface { Work() } type SeedWorker struct{} ! func (self *SeedWorker) Work() { // work... }
  144. 144. interface // accept anything implements // the interface of Worker func HandleData(worker Worker) { worker.Work() } ! func main() { HandleData(SeedWorker{}) HandleData(&SeedWorker{}) }
  145. 145. interface{} • interface{} is basically a universal pointer. • just like “id” we used in Objective-C • just like the void pointer we used in C. • interface{} means an interface without requirement.
  146. 146. interface{} Given Struct Foo and Bar type Foo struct{} type Bar struct{}
  147. 147. interface{} Given Struct Foo and Bar type Foo struct{} type Bar struct{} var var var b = a = a interface{} = Foo{} b interface{} = &Foo{} c interface{} = &Bar{} c b
  148. 148. interface{} type anything interface{} var a anything = Foo{} var b anything = &Foo{} var c anything = &Bar{}
  149. 149. interface{} type anything interface{} func AcceptAnything(a anything) { // do something } func main() { AcceptAnything(Foo{}) AcceptAnything(&Foo{}) AcceptAnything(&Bar{}) }
  150. 150. Building Web Applications Using net/http
  151. 151. Data Structure For Page $ mkdir wiki $ cd wiki $ vim page.go
  152. 152. Data Structure For Page package main ! import ( "fmt" "io/ioutil" )
  153. 153. Data Structure For Page type Page struct { Title string Body []byte }
  154. 154. Data Structure For Page type Page struct { Title string Body []byte } func (p *Page) save() error { filename := p.Title + ".txt" return ioutil.WriteFile(filename, p.Body, 0600) }
  155. 155. Data Structure For Page func loadPage(title string) (*Page, error) { filename := title + ".txt" body, err := ioutil.ReadFile(filename) if err != nil { return nil, err } return &Page{Title: title, Body: body}, nil }
  156. 156. Build it! $ go build wiki.go
  157. 157. Build it! $ go build wiki.go $ ./wiki This is a sample page.
  158. 158. Introducing net/http package main ! import ( "fmt" "net/http" )
  159. 159. Introducing net/http Type of Handler func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:]) }
  160. 160. Introducing net/http Resource handle which implements Writer interface. func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:]) }
  161. 161. Introducing net/http func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:]) } Call w.Write… (this satisfies Writer interface)
  162. 162. Introducing net/http func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:]) } ! func main() { http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil) } Calls the HandleFunc function in “http” package. This function accepts a function pointer which satisfies the interface.
  163. 163. Introducing net/http func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:]) } ! func main() { http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil) } Binds HTTP server to “:8080”
  164. 164. Introducing net/http http://localhost:8080/monkeys Hi there, I love monkeys!
  165. 165. Using net/http package main ! import ( "fmt" "io/ioutil" "net/http" ) Import http package.
  166. 166. Using net/http func viewHandler(w http.ResponseWriter, r *http.Request) { title := r.URL.Path[len("/view/"):] p, _ := loadPage(title) fmt.Fprintf(w, "<h1>%s</h1><div>%s</div>", p.Title, p.Body) } The URL of current request
  167. 167. Using net/http func viewHandler(w http.ResponseWriter, r *http.Request) { title := r.URL.Path[len("/view/"):] p, _ := loadPage(title) fmt.Fprintf(w, "<h1>%s</h1><div>%s</div>", p.Title, p.Body) } Strip the first 6 bytes from URL Path
  168. 168. Using net/http func viewHandler(w http.ResponseWriter, r *http.Request) { title := r.URL.Path[len("/view/"):] p, _ := loadPage(title) fmt.Fprintf(w, "<h1>%s</h1><div>%s</div>", p.Title, p.Body) } Load the page data from file.
  169. 169. Using net/http func main() { http.HandleFunc("/view/", viewHandler) http.ListenAndServe(":8080", nil) }
  170. 170. Build it! $ go build wiki.go
  171. 171. Build it! $ $ $ $ vim test.txt go build wiki.go ./wiki curl http://localhost:8080/view/test
  172. 172. Edit handler func editHandler(w http.ResponseWriter, r *http.Request) { title := r.URL.Path[len("/edit/"):] p, err := loadPage(title) if err != nil { p = &Page{Title: title} } fmt.Fprintf(w, "<h1>Editing %s</h1>"+ "<form action="/save/%s" method="POST">"+ "<textarea name="body">%s</textarea><br>"+ "<input type="submit" value="Save">"+ "</form>", p.Title, p.Title, p.Body) }
  173. 173. The html/template package package main ! import ( "html/template" "io/ioutil" "net/http" )
  174. 174. The html/template package func editHandler(w http.ResponseWriter, r *http.Request) { title := r.URL.Path[len("/edit/"):] p, err := loadPage(title) if err != nil { p = &Page{Title: title} } t, _ := template.ParseFiles("edit.html") t.Execute(w, p) }
  175. 175. The html/template package <h1>Editing {{.Title}}</h1> ! <form action="/save/{{.Title}}" method="POST"> <div><textarea name="body" rows="20" cols="80">{{printf "%s" .Body}}</textarea></div> <div><input type="submit" value="Save"></div> </form>
  176. 176. Save handler func saveHandler(w http.ResponseWriter, r *http.Request) { title := r.URL.Path[len("/save/"):] body := r.FormValue("body") p := &Page{Title: title, Body: []byte(body)} p.save() http.Redirect(w, r, "/view/"+title, http.StatusFound) } ! http.HandleFunc(“/save/“, saveHandler) ! http://localhost:8080/edit/test # access test.txt
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×