go语言基础知识

一、一个简单的Go程序

下面这个程序是一个http请求,输出返回的body字段。panic会立即中断函数流程,执行延时调用。从下面这个程序可以看出通过go访问http非常简洁。

package main

import (
	"net/http"
	"io/ioutil"
	"fmt"
)

func main() {

	r, err := http.Get("http://httpbin.org/anything?hello=world")
	if err != nil {
		panic(err)
	}
	defer r.Body.Close()

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		panic(err)
	}
	fmt.Printf("body = %s\n", string(body))
	
}

二、Go语言数据类型

  • uint 32位或64位
  • uint8 无符号 8 位整型 (0 到 255)
  • uint16 无符号 16 位整型 (0 到 65535)
  • uint32 无符号 32 位整型 (0 到 4294967295)
  • uint64 无符号 64 位整型 (0 到 18446744073709551615)
  • int 32位或64位
  • int8 有符号 8 位整型 (-128 到 127)
  • int16 有符号 16 位整型 (-32768 到 32767)
  • int32 有符号 32 位整型 (-2147483648 到 2147483647)
  • int64 有符号 64 位整型 (-9223372036854775808 到 9223372036854775807)
  • byte uint8的别名(type byte = uint8)
  • rune int32的别名(type rune = int32),表示一个unicode码
  • uintptr "无符号整型,用于存放一个指针是一种无符号的整数类型,没有指定具体的bit大小但是足以容纳指针。uintptr类型只有在底层编程是才需要,特别是Go语言和C语言函数库或操作系统接口相交互的地方。"
  • float32 IEEE-754 32位浮点型数
  • float64 IEEE-754 64位浮点型数
  • complex64 32 位实数和虚数
  • complex128 64 位实数和虚数
  • string 字符串,默认值是空字符串,而非NULL
  • array 数组
  • struct 结构体,类似java里面的对象
  • function 函数,默认值nil
  • interface 接口,默认值nil
  • map 字典,引用类型,默认值nil
  • slice 切片,动态的数组,引用类型,默认值nil
  • channel 通道,引用类型,默认值nil

三、 Go语言系统关键字

  • break default func interface select
  • case defer go map struct
  • chan else goto package switch
  • const fallthrough if range type
  • continue for import return var

四、Go语言预定标识符

  • append bool byte cap close complex
  • complex64 complex128 uint16 copy FALSE float32
  • float64 imag int int8 int16 uint32
  • int32 int64 iota len make new
  • nil panic uint64 print println real
  • recover string TRUE uint uint8 uintprt

五、Go语言变量

package main

import "fmt"

func main() {
	// 使用var定义变量,支持类型推断
	var x int32
	var s = "hello,world"
	fmt.Println(x, s)

	// 在函数内部,可以省略var关键字
	y := 100
	fmt.Println(y)

	// 编译器将未使用的局部变量定义当作错误
	//z := 200
}

六、Go语言--表达式

package main

import "fmt"

func main() {

	x := 100
	if x > 0 {
		fmt.Println("x")
	} else if x < 0 {
		fmt.Println("-x")
	} else {
		fmt.Println("0")
	}

	switch {
	case x > 0:
		fmt.Println("x")
	case x < 0:
		fmt.Println("-x")
	default:
		fmt.Println("0")
	}

	for i:=0; i <5; i++ {
		fmt.Println(i)
	}

	// 相当于while (x < 5) { ... }
	for x < 5 {
		fmt.Println(x)
		x++
	}
	// 相当于while (true) { ... }
	for {
		fmt.Println(x)
		x--
		if x < 0 {
			break
		}
	}
	// 迭代遍历,除返回元素外,还返回索引
	s := []int{100, 200, 300}
	for i, n := range s {
		fmt.Println(i, n)
	}
}

七、Go语言--函数

package main

import (
	"errors"
	"fmt"
)

// 定义多个变量接受,多返回值
func div(a, b int) (int, error) {
	if b == 0 {
		return 0, errors.New("division by zero")
	}
	return a / b, nil
}

// 函数作为第一类型,可作为参数或返回值
func test(x int) func() {
	// 匿名函数
	return func() {
		fmt.Println(x)


	}
}

func main() {
	a , b := 10, 2
	c, err := div(a, b)
	fmt.Println(c, err)

	x := 100
	f := test(x)
	f()
}

八、Go语言--slice

切片是有三个字段的数据结构,指向底层数组的指针,切片访问元素的个数(长度),切片允许增长到的元素的个数(容量),这种数据结构便于使用和管理数据集。切片围绕动态数组的概念构建的,可以按需自动增长和缩小。切片是一个很小的对象,对底层数组进行了抽象,并提供相关的操作方法,切片的底层内存是在连续块中分配的。

package main

import "fmt"

func main() {
	// 创建一个整型切片,其长度为3,容量为5
	s := make([]int, 3, 5)
	for i := 0; i < 3; i++ {
		s[i] = i
	}
	// 创建一个整型切片,其长度和容量都是5
	slice := []int{10, 20, 30, 40, 50}
	// 创建一个新切片,其长度为2,容量为4
	newslice := slice[1:3]
	// 使用原有的容量来分配一个新元素
	// 如果切片的底层数组没有足够的容量,append会创建一个新的底层数组,这个数组容量是原来的两倍
	newslice = append(newslice, 60)
	// 5 5
	fmt.Println(cap(slice), len(slice))
	// 4 3
	fmt.Println(cap(newslice), len(newslice))
	// 迭代切片,第一个值当前迭代索引位置,第二个该元素对应值的一份副本
	for index, value := range newslice {
		fmt.Printf("index:%d value:%d\n", index, value)
	}
}

九、Go语言--map

map(映射)是一种数据结构,用于存储一系列无序的键值对。

package main

import "fmt"

func main() {

	// 创建一个映射,键的类型是string,值的类型是int
	dict := make(map[string]int)
	// map[]
	fmt.Println(dict)
	// 创建一个映射,键和值的类型都是string,使用两个键值对初始化映射
	colors := map[string]string{"red":"red","blue":"blue"}
	// map[red:red blue:blue]
	fmt.Println(colors)
	// 从映射获取值并判断键是否存在
	value, exits := colors["blue"]
	if exits {
		// blue
		fmt.Println(value)
	}
	//删除键为blue的键值对
	delete(colors, "blue")
	// 使用range迭代映射
	for key, value := range colors {
		// key:red value:red
		fmt.Printf("key:%s value:%s\n", key, value)
	}
}

十、Go语言--结构体

结构类型可以用来描述一组数据值,这组值的本质既可以是原始的,也可以是非原始的。

package main

import "fmt"
// 结构体类型
type user struct {
	name string
	age byte
}

type manager struct {
	// 匿名嵌入其他类型
	user
	title string
}

func main() {
	var m manager
	// 直接访问匿名字段成员
	m.name = "james"
	m.age = 34
	m.title = "CTO"
	fmt.Println(m)
}

十一、Go语言--指针

package main

// 内存地址是内存中每个字节单元的唯一编号
// 指针是一个实体,指针会分配内存空间,相当于一个专门用来保存地址的整型变量
func main() {
	x := 10
	// 获取地址保存到指针变量
	var p *int = &x
	// 用指针间接引用,并更新对象
	*p +=10
	// 0xc00002bf70 20
	println(&x, x)
	// 0xc00002bf70 20 0xc00002bf80
	println(p, *p, &p)
	
}

十二、Go语言--方法

package main

import "fmt"

type student struct {
	name string
	age byte
}
// 方法能给用户定义的类型添加新的行为,方法实际上也是函数
// 只是在声明时,在func和方法名之间增加一个参数,成为recevier
func (s student) toString() string {
	return fmt.Sprintf("%+v", s)
}

func main() {
	s := student{"james", 34}
	fmt.Println(s.toString())
}

十三、Go语言--接口

接口是用来定义行为的类型,这些被定义的行为不由接口直接实现,而是通过方法由用户定义的类型实现。
Go接口实现机制很简洁,只要目标类型方法包含接口声明的全部方法,就被视为实现了该接口,无需做显示声明。当然,目标类可以实现多个接口。
如果接口没有任何方法声明,那么就是一个空接口(interface{}),它的用途类似Object,可被赋值为任何类型的对象。

package main

import "fmt"

// 定义tester接口,定义两个方法
type tester interface {
	test()
	string() string
}
// 顶一个结构体data,实现接口tester
type data struct {}

func (d *data) test() {}

func (d data) string() string {
	return "I Love China"
}
func main() {

	var d data
	// data没有实现tester,test()是指针接收者声明
	var t tester = &d
	t.test()
	fmt.Println(t.string())
}

go多态的例子:

package main

import "fmt"

// notifer是一个定义了通知类行为的接口
type notifer interface {
	notify()
}
// user定义了一个用户类型
type user struct {
	name string
	email string
}
// notify使用指针接收者实现了notifier的接口
func (u *user) notify() {
	fmt.Printf("Sending user email to %s<%s>\n", u.name, u.email)
}
// admin定义了程序的管理员
type admin struct {
	name string
	email string
}
// notify使用指针接收者实现了notifier的接口
func (a *admin) notify() {
	fmt.Printf("Sending user email to %s<%s>\n", a.name, a.email)
}
// sendNotification接受了一个实现notifer的值,并发送通知
func sendNotification(n notifer) {
	n.notify()
}
func main() {
	jack := user{"jack","jack@jd.com"}
	// 创建一个user值并传给sendNotification
	sendNotification(&jack)
	rose := admin{"rose", "rose@jd.com"}
	// 创建一个admin值并传给sendNotification
	sendNotification(&rose)
	
}

posted @ 2019-09-24 10:01  wudiffs  阅读(283)  评论(0编辑  收藏  举报