目錄java
學習golang注意點:python
- 導的包必須使用;或者使用
_
未使用的包,做用是調用該包下的初始化方法。- 局部變量聲明必須使用。
- go語言的包和java的類似,
包名.變量
訪問
package main import "fmt" func main() { fmt.Println("hello world"); }
var a bool = true var b bool = false
整型分爲有符號和無符號的類型golang
8, 16 ,32 分別表明位數編程
int
: 根據系統決定是32位還64位json
int8
: 1個字節,-128~127 至關於java中的short;數組
int16
: 2個字節,-215 ~ 215 -1網絡
int32
: 4個字節 -231 ~231 - 1數據結構
int64
: 8個字節-263 ~263 - 1閉包
uint : .....app
無符號整形都是取值0~216 - 1
var a int = -3 var b uint = 3 //uint類型不能夠爲負數
var a float32 = 100.0 var b float64 = 100.00 //默認
golang中的字符使用的是字節保存的,本質就是一個int32類型
var a byte = 'a' var b byte = 'c' fmt.Print(a, "===", b) //輸出的是該字節對應的字節碼: 97===99 fmt.Printf("%c === %c", a, b) // a === c
var str string = "hello world" //多行字符串,不須要使用+來鏈接多行 var str2 string = `a asda asdasdadsadasd `
complex64
是兩個float32組成 complex128
兩個float64組成
var a complex64 = 10 + 3i var b complex128= 10 + 3i //默認
相關操做
var v= complex(2 , 3) //構造1個複數, a := real(v) //返回複數實部 2 b := image(v) 返回複數虛部 3
rune類型:
// rune is an alias for int32 and is equivalent to int32 in all ways. It is // used, by convention, to distinguish character values from integer values. //int32的別名,幾乎在全部方面等同於int32 //它用來區分字符值和整數值 type rune = int32
屬於函數或者方法;聲明以後必須使用
var a = 3; var b int = 3; c := 3
b := 10
這種全局變量聲明是錯誤的
全局變量的概念:隸屬於包
,聲明以後能夠不使用
var a int var ( c int d string ) var e = 3
局部
const a = 3
全局
const a int = 10 const b = 20 const ( d int = 10 e string = "ss" f = 30 )
golang中string底層是經過byte數組實現的,byte使用utf-8編碼標識的Unicode文本,每一個漢字佔3個字節
func strDemo() { fmt.Println(len("hello")) //5 fmt.Println(len("中")) //3 fmt.Println(len([]rune("中"))) //1, 正確獲取中文字符串長度 }
//對中文沒法支持 func strEach() { str := "hello world" for i := 0; i < len(str); i ++ { //fmt.Print(str[i] ,"\t") // 104 101 108 108 111 32 119 111 114 108 100 //講字節編碼轉爲字符串輸出 fmt.Printf("%c\t", str[i]) //h e l l o w o r l d } }
func strEach() { str := "hello world 中國" for i, s := range str { //0 h1 e2 l3 l4 o5 6 w7 o8 r9 l10 d11 12 中15 國 fmt.Print(i, "\t", string(s)) } } //這個能夠正確的輸出索引 func strEachRune() { str := "中國人民" for i, s := range []rune(str) { fmt.Println(i, string(s)) } }
str := "中國人民, hello world" index := strings.Index(str, "國") //存在則 index > -1, 不然 == -1 此時index=-3 split := strings.Split(str, ",") replace := strings.Replace(str, "o", "2", 1) //第三個參數標識替換幾個,小於0,則替換全部 result := strings.EqualFold("中國", "中國2") //不區分大小寫 fmt.Println("中國" == "中國H") //區分大小寫, 同strings.Compare()5
golang基本數據數據之間的轉換可以使用公:T(i)
進行相互轉換
//數據之間的相互轉換 func transfer() { // var i int = 10 var j float64 = 11.30 x := float64(i) y := int(j) fmt.Print(x, "\t", y) //10 11 }
fmt.Sprintf(format string, param interface{})
func stringTrans() { var i int = 10 var flag bool = true int_str := fmt.Sprintf("%d", i) bool_str := fmt.Sprintf("%t", flag) fmt.Println(int_str) fmt.Println(bool_str) }
strconv
func stringStrco() { var i int = 10000 var flag bool = true var price float64 = 130.32 formatInt := strconv.FormatInt(int64(i), 10) //等價: strconv.Itoa(i) formatBool := strconv.FormatBool(flag) formatFloat := strconv.FormatFloat(price, 'f', 10, 64) fmt.Println(formatInt) fmt.Println(formatBool) fmt.Println(formatFloat) }
func strToBase() { str_flag := "true" str_age := "20" str_price := "20.33" flag, _ := strconv.ParseBool(str_flag) age, _ := strconv.ParseInt(str_age, 10, 64) age_int, _ := strconv.Atoi(str_age) price, _ := strconv.ParseFloat(str_price, 64) fmt.Println(flag) fmt.Println(age) fmt.Println(price) fmt.Println(age_int) }
1.6.3 字節數組和字符串
func byteAndStr() { str := "hello world, 中國" data := []byte(str) s := string(data) fmt.Println(s) fmt.Println(data) }
func timeOperate() { cur := time.Now() curT := time.Now().Unix() //獲取時間戳 fmt.Println(cur) //2019-01-30 20:40:16.410689 +0800 CST m=+0.000353772 fmt.Println(curT) //1548852137 }
func formatTime() { format := time.Now().Format("2006-01-02 15:04:05") //時間戳轉時間 var timestamp int64 = 1548852137 unix := time.Unix(timestamp, 0).Format("2006-01-02 15:04:05") //字符串轉時間 formatTimeStr := "2017-04-11 13:33:37" strToTime, _ := time.Parse("2006-01-02 15:04:05", formatTimeStr) fmt.Println(format) //2019-01-30 21:00:53 fmt.Println(unix) fmt.Println(strToTime) //2017-04-11 13:33:37 +0000 UTC }
數組和切片(slice)之間的區別:
數組:聲明的時候必須指定長度
var arr [10]int
,值類型,可是在java裏面數組是引用類型 Slice: 長度可變,不須要指定長度,引用類型
//數組的聲明 func createArray() { var books [3]string books[0] = "java" books[1] = "python" books[2] = "golang" names := [3]string{"lisi", "zhansan", "hand"} scores := [...]int{89, 59, 30, 100} //根據後面的內容決定長度 fmt.Println(books) fmt.Println(names) fmt.Println(scores) } //數組的相關操做 func operateArray() { //數組長度 scores := [...]int{89, 59, 30, 100} fmt.Println(len(scores)) //數組遍歷 for i := 0; i < len(scores); i++ { fmt.Print(scores[i], "\t") } fmt.Println() for index, value := range scores { fmt.Print(index, "==", value, "\t") } }
slice是一個比較複雜的數據結構,也就至關於Java裏面集合的概念,是一個可變長的數據
//最簡單的一種聲明方式 func createSlice() { var args []int args = make([]int, 10) args[0] = 1 args[1] = 2 args[2] = 3 args[3] = 4 args[4] = 5 for index, value := range args { fmt.Println(index, value) } }
經過數組定義一個切片
len
切片長度, 表示當前切片元素的個數
cap
切片容量,表示切片能夠容納切片的個數,若是超出則報錯
func createSlice2() { arrays := [...]int{1, 2, 3, 4, 5} slice := arrays[1:4] //[2 3 4] fmt.Println(len(slice)) //3 fmt.Println(cap(slice)) //4 slice[1] = 10 //這裏能夠解釋下圖 fmt.Println(arrays) //[1 2 10 4 5] fmt.Println(slice) // [2 10 4] }
這裏容量爲何是4?,如圖
append©函數
當append超出原來容量的時候,會擴展原來的容量爲原先的兩倍
//append func appendFunc() { slice := make([]int, 2, 4) slice[0] = 1 slice[1] = 1 slice = append(slice, 2) slice = append(slice, 3) slice = append(slice, 4) fmt.Println(len(slice)) //5 fmt.Println(cap(slice)) //8 } //copy函數的用法 func copyFunc() { slice := make([]int, 2, 4) slice2 := make([]int, 2, 4) slice[0] = 1 slice[1] = 1 copy(slice2, slice) //至關於 slice2 := slice[:] fmt.Println(slice2) // [1 1] }
map 數據結構和java的HashMap相似。
//建立一個map func createMap() { var product map[string]interface{} //聲明 product = make(map[string]interface{}) //初始化 product["id"] = 1 product["title"] = "口紅" product["price"] = 199.33 fmt.Println(product) } //遍歷map func mapForEach() { var product map[string]interface{} //聲明 product = make(map[string]interface{}) //初始化 product["id"] = 1 product["title"] = "口紅" product["price"] = 199.33 for key, value := range product { fmt.Println(key, value) } }
go語言中的結構體和Java中的類很類似,包含屬性,方法等內容。首字母大寫對其餘包可見,首字母小寫只是對本包可見。
指針和值類型: 指針類型的方法能夠修改屬性的值,值類型的不能夠修改,
package main import "fmt" func main() { student := &Student{"zhansn", 24} fmt.Println(student.GetName())//zhansn student.SetName("lisi") fmt.Println(student.GetName()) //lisi } //對屬性小寫能夠封裝 type Student struct { name string age int } //定義結構體的方法GetName和SetName func (this Student) GetName() string { return this.name } //這裏使用指針能夠改變屬性的內容 func (this *Student) SetName(name string) { this.name = name }
在go語言中結構體和結構體沒有繼承,而是經過組合的方式來獲取其餘結構體的方法。此時的Student可使用Person的全部屬性和方法,不管是否封裝。
package main import "fmt" func main() { student := &Student{} fmt.Println(student.GetName()) // "" student.SetName("lisi") fmt.Println(student.GetName()) //lisi } //對屬性小寫能夠封裝 type Student struct { Person } type Person struct { name string age int } //定義類型的方法 func (this Person) GetName() string { return this.name } //這裏使用指針能夠改變屬性的內容 func (this *Person) SetName(name string) { this.name = name }
golang接口中沒有變量,只有方法。
對於java中的多態描述:重載和重寫兩種多態。可是在golang中沒法對方法進行重載,由於golang是一門面向函數編程的語言。因此golang能夠經過重寫來實現多態,並且是接口和子類之間的重寫。
package main import "fmt" func main() { ben := &Ben{"benchi"} ao := &Ao{"aodi"} ToString(ben) ToString(ao) } type Car interface { GetName() string SetName(name string) } func ToString(car Car) { fmt.Println(car.GetName()) } type Ben struct { name string } func (ben Ben) GetName() string { return ben.name } func (ben *Ben) SetName(name string) { ben.name = name } type Ao struct { name string } func (this Ao) GetName() string { return this.name } func (this *Ao) SetName(name string) { this.name = name }
golang 類型斷言和java中的instanceof
關鍵字類似,可是又比這個關鍵字高級,好用,實現方式val.(T)
func main() { var x interface{} x = 4 if y, ok := x.(int); ok { fmt.Println(y) } }
斷言接口子類
package main import "fmt" func main() { ben := Ben{"benchi"} ao := Ao{"aodi"} ToString(ben) ToString(ao) } type Car interface { GetName() string } func ToString(car Car) { if ben, ok := car.(Ben); ok { fmt.Println(ben.GetName()) } else if ao, ok := car.(Ao); ok { fmt.Println(ao.GetName()) } else { fmt.Println("other type") } } type Ben struct { name string } func (ben Ben) GetName() string { return ben.name } type Ao struct { name string } func (this Ao) GetName() string { return this.name }
以下代碼,有什麼問題呢?此時咱們使用指針類型是實現了接口notify
的方法,那麼在SendNotify(u notify)
中咱們必須使用子類的指針做爲參數傳遞到該函數,若是咱們使用值類型實現接口notify
的方法,例如func (this user) Notify()
這樣既可使用指針也可使用值傳遞參數。
package main import "fmt" func main() { u := &user{"hello"} //此時必須傳遞指針參數 SendNotify(u) } type notify interface { Notify() } type user struct { name string } //指針實現接口 func (this *user) Notify() { fmt.Println(this.name) } func SendNotify(u notify) { u.Notify() }
這是爲何呢?
對於一個方法method(param T)
能夠接受值類型
和指針類型
的參數,method(param *T)
僅僅能夠接受指針類
型的參數。
java中有函數式編程,集合框架中有一個消費型函數forEach
,咱們在golang中經過閉包實現該函數
package main import "fmt" func main() { data := []int{1,2,3,4,5} forEach(data, func(index int, value interface{}) { fmt.Println(index, value) }) } func forEach(data []int, f func(int, interface{})) { for index, value := range data { f(index, value) } }
defer
會在函數或者方法結束前被調用,和Java中finally
類似
func main() { /** first hello world defer is called */ say() } func say() { fmt.Println("first") defer fmt.Println("defer is called") fmt.Println("hello world") } //因爲return了,因此return後面的語句不會被執行 func say2() { fmt.Println("first") return defer fmt.Println("defer is called") fmt.Println("hello world") }
defer
使用場景:錯誤處理,關閉資源,釋放鎖,後續會見到這些使用操做
這裏訴說的錯誤處理和Java中的異常處理同樣,在java語言中錯誤處理通常都是try...catch…finally,而在golang語言中經過三個關鍵字對錯誤盡心處理:(defer recover) panic
func catchError() { defer func() { err := recover() if err != nil { fmt.Println("出現異常", err) } }() a := 10 b := 0 x := a / b fmt.Println(x) }
func catchError() { //在這裏捕獲處理,若是不進行捕獲,則程序會崩潰 defer func() { err := recover() if err != nil { fmt.Println("出現異常", err) } }() err := selfError() //向外拋出異常 panic(err) } func selfError() error { return errors.New("自定義異常") }
package main import "log" func main() { // info:2019/02/04 16:47:25 LoggerDemo.go:6: message log.Println("message") } func init() { log.SetPrefix("info:") log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) }
func main() { log.Println("message") //Fatalln執行以後調用:os.Exit(1), 退出程序,後續程序再也不執行 log.Fatalln("打印日誌,程序退出") fmt.Println("還會執行嗎") }
package logger import ( "log" "os" "io" ) var ( Debug *log.Logger //僅僅輸出到控制檯 Info *log.Logger Warning *log.Logger Error *log.Logger ) const ( logFlag = log.LstdFlags | log.Lshortfile ) func init() { file, error := os.OpenFile("info.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) if error != nil { panic(error) } Debug = log.New(os.Stdout, "debug:", logFlag) Info = log.New(io.MultiWriter(file, os.Stdout), "info:", logFlag) Warning = log.New(os.Stdout, "waring:", logFlag) Error = log.New(io.MultiWriter(file, os.Stderr), "error:", logFlag) }
測試
package main import "logger" func main() { logger.Debug.Println("debug") logger.Info.Println("create a info log") logger.Error.Println("create a errr log") }
package main import ( "os" "fmt" "bufio" "io" "io/ioutil" ) func openFile() { file, err := os.Open("info.log") if err != nil { fmt.Println("文件錯誤", err) } defer file.Close() reader := bufio.NewReader(file) for { str, err := reader.ReadString('\n') if err == io.EOF { //表示讀取完畢 break } fmt.Print(str) } } //讀取內容到內存中 func openFile2() { data, err := ioutil.ReadFile("info.log") if err != nil { } fmt.Print(string(data)) } func writeFile() { file, err := os.OpenFile("hello.txt", os.O_WRONLY| os.O_CREATE | os.O_APPEND, 0666) if err != nil { fmt.Println("建立文件錯誤") return } defer file.Close() writer := bufio.NewWriter(file) for i := 0; i < 5; i++ { writer.WriteString("寫入數據:\n") } writer.Flush() //將緩衝區內容寫入到文件中 } //判斷文件是否存在 func IsExist() { _, e := os.Stat("info2.log") if e != nil { exist := os.IsNotExist(e) fmt.Println(exist) } }
package main import ( "encoding/json" "fmt" "time" ) type Book struct { Title string Author string Publish time.Time } //序列化map func serializeMap() { student := make(map[string]interface{}) student["name"] = "閏土" student["age"] = 20 student["class"] = "大一" bytes, err := json.Marshal(student) if err != nil { fmt.Println("序列化錯誤") } fmt.Println(string(bytes)) //{"age":20,"class":"大一","name":"閏土"} } //序列化結構體 func serializeStruct() { book := Book{"青春","itcloud", time.Now()} bytes, _ := json.Marshal(book) fmt.Println(string(bytes)) // {"Title":"青春","Author":"itcloud","Publish":"2019-02-05T11:14:51.094709+08:00"} } func deserializeMap() { var student map[string]interface{} data := `{"age":20,"class":"大一","name":"閏土"}` err := json.Unmarshal([]byte(data), &student) if err != nil {} fmt.Println(student) } func deserializeStruct() { var book Book bookStr := `{"Title":"青春","Author":"itcloud","Publish":"2019-02-05T11:14:51.094709+08:00"}` json.Unmarshal([]byte(bookStr), &book) fmt.Println(book) }
客戶端
package main import ( "bufio" "fmt" "net" "os" ) func main() { conn, _ := net.Dial("tcp", "127.0.0.1:8088") reader := bufio.NewReader(os.Stdin) line, _ := reader.ReadString('\n') n, _ := conn.Write([]byte(line)) fmt.Println(n) }
服務端
package main import ( "fmt" "net" ) func main() { listener, err := net.Listen("tcp", "127.0.0.1:8088") if flag := Checkout(err, "監聽開啓錯誤"); !flag { return } defer listener.Close() for { fmt.Println("等待客戶端創建鏈接...") conn, err := listener.Accept() if flag := Checkout(err, "打開鏈接失敗"); flag { fmt.Printf("conn= %v, ip = %v\n", conn, conn.RemoteAddr().String()) } go process(conn) } } func process (conn net.Conn) { defer conn.Close() for { buf := make([]byte, 1024) readLen, err := conn.Read(buf) if flag := Checkout(err, "讀取失敗"); !flag { return } fmt.Println(string(buf[:readLen])) } } func Checkout(err error, msg string) bool { if err != nil { fmt.Println(msg, err) return false } return true }
func main() { http.HandleFunc("/echo", echo) http.ListenAndServe(":8080", nil) } func echo(w http.ResponseWriter, r *http.Request) { body, err := ioutil.ReadAll(r.Body) if err != nil { w.Write([]byte("get body error")) return } strlen, err := w.Write(body) if err != nil && strlen != len(body) { w.Write([]byte("write a error")) } }
package main import ( "net/http" "time" ) //自定義handler func main() { myHandler := &SelfHandle{format: time.RFC1123} http.Handle("/time", myHandler) http.ListenAndServe(":8080", nil) } type SelfHandle struct { format string } func (h *SelfHandle) ServeHTTP(w http.ResponseWriter, r *http.Request) { forTime := time.Now().Format(h.format) w.Write([]byte("time is " + forTime)) }
多路複用處理器
package main import "net/http" //多路複用處理器 func main() { mux := http.NewServeMux() mux.HandleFunc("/hello", hello) mux.HandleFunc("/world", world) server := &http.Server{Addr: ":8080", Handler: mux} server.ListenAndServe() } func hello(w http.ResponseWriter, r *http.Request) { w.Write([]byte("hello")) } func world(w http.ResponseWriter, r *http.Request) { w.Write([]byte("word")) }