博主学习时总结的一些基础知识点。拿捏!
一个名字必须以一个字母(Unicode字母)或下划线开头,后面可以跟任意数量的字母、数字或下划线。大写字母和小写字母是不同的
var a int = 1
var b int = 2
// 也可以依赖自动类型判断
var a = 1
var b = 2
// 也可以批量赋值
var (
a int = 1
b int = 2
c = 1
d = 2
)
// 还可以更简单的下
a:=1
b:=2
// 还可以这样批量赋值【元组赋值】
a:=1
b:=2
// 交换两个的值
a,b = b,a
const (
one = 1
two = 2
three = 3
)
// 等效于
const(
one = ital + 1
two
three
)
const(
Readable = 1 << iota //0001
Writeable //0010
Executable // 0100
)
Go语言将数据类型分为四类:
bool
string
int int8 int16 int32 int64
unit unit8 unit16 unit32 unit64 unitptr
byte //等同于unit8
rune // 等同 int32 unitcode编码指针
float32 float64
complex64 complex128
string 是只读的 byte slice ,len 函数可以计算它所包含的 byte 数, string 的 byte 数组可以存放任何数据
// 普通循环
n:= 0
for n < 5 {
n++
fmt.PrintLn(n)
}
//普通循环三次
for n:=0; n < 3; n++ {
}
// 无限循环
n := 0
for {
...
}
// 条件语句
if n==5 {
}
//多判断,函数支持多个返回值
if result,err := someThing(); err == nil {
}
//switch 使用,支持case 后面接多个值,且不用带 break
i:=32
switch i {
case 1:
t.Log(1)
case 2,32:
t.Log(32)
default:
t.Log(3)
}
// 支持多返回值
func test(a string, b *T) (result string, err error) {
return "ok", nil
}
a, err := test("a", &b);
if (err != nil) {
return err;
}
// 匿名函数
func squares() func() int {
var x int
return func() int {
x++
return x * x
}
}
//可变参数
func sum(vals ...int) int {
total := 0
for _, val := range vals {
total += val
}
return total
}
// 延迟函数,执行顺序和声明相反
defer resp.Body.Close()
func timeSpent(inner func (op int) int) func(op int) int {
return func (n int) int {
start := time.Now()
ret := inner(n)
fmt.Println("time spent", time.Since(start).Seconds())
return ret
}
}
func slowFun(op int) int {
time.Sleep(time.Second * 1)
return op
}
ts := timeSpent(slowFun)
ts(10)
// 定义接口
type Programmer interface {
Say() string
}
// 定义类
type GoProgrammer struct {
}
// 定义方法,方法定义和接口相同就是实现了这个接口
func (g *GoProgrammer) Say() string {
return "hello"
}
func main() {
// 定义接口变量
var p Programmer
// 实现接口
w = new(GoProgrammer)
// 调用接口方法
w.Say()
}
type Pet struct {
}
type Dog struct {
Pet
}
func (p *Pet) Say() {
fmt.Println("pet is saying")
}
func (p *Pet) Eat() {
fmt.Println("pet is eating")
}
func (d *Dog) Say() {
fmt.Println("dog is saying")
}
func TestExtension(t *testing.T) {
dog := new(Dog)
dog.Eat() //pet is eating
dog.Say() // dog is saying
}
errors.New("test")
func TestRecover(t *testing.T) {
defer func() {
if err := recover() ; err != nil {
fmt.Println(err)
}
fmt.Print("over")
}()
panic(errors.New("problem"))
}
// 如果main协程退出,那么所有协程都会退出
func TestMyGo(t *testing.T) {
for i:=0 ; i < 10 ; i++ {
go func(i int) {
fmt.Println(i)
}(i)
time.Sleep(100 * time.Microsecond)
}
}
// 使用锁机制避免资源竞争
var mut sync.Mutex
counts := 0;
for i:=0 ; i < 5000 ; i++ {
go func() {
defer func() {
mut.Unlock() //解锁
}()
mut.Lock() // 锁住
counts++
}()
}
time.Sleep(time.Second)
println(counts)
}
// 创建一个 channel (带缓冲区和不带缓冲区的)
ch1 := make(chan string)
ch2 := make(chan string, 2)
// 往通道里面写东西
go func() {
ch1 <- "go"
ch2 <- "php"
}()
// 读通道
println(<-ch1)
for ret := range ch2
// 关闭channel
close(ch1)
close(ch2)
// 多渠道的选择
select {
case ret := <-retCh1:
t.Log(ret)
case ret := <-retCh2:
t.Log(ret)
default:
t.Error("No one returned")
}
// 超时控制
select {
case ret := <-retCh:
t.Log(ret)
case <-time.After(time.Second):
t.Log("time out")
}
func TestChannelClose(t *testing.T) {
ch := make(chan int)
var wg sync.WaitGroup
wg.Add(1)
dataProducer(ch, &wg)
wg.Add(1)
dataReceiver(ch, &wg)
wg.Wait()
}
// 生产者
func dataProducer(ch chan int , wg *sync.WaitGroup) {
go func() {
for i:=0; i < 20; i++ {
ch <-i
}
close(ch) // 如果不关闭通道,获取的时候一直返回了的是 零值, true 。只有关闭的时候才会返回 nil, false
wg.Done()
}()
}
// 消费者
func dataReceiver(ch chan int , wg *sync.WaitGroup) {
go func() {
for{
if data, ok := <-ch; ok {
fmt.Println(data)
}else {
break
}
}
wg.Done()
}()
}
func TestCloseChannel(t *testing.T) {
ch := make(chan int)
for i:=0 ; i < 5 ; i++ {
// 创建五个协程
go func(i int, ch chan int) {
for {
if isCancel(ch) {
// 能消费到就会退出
break
}
time.Sleep(time.Microsecond * 5)
}
fmt.Println(i, "cancel")
}(i, ch)
}
cancle1(ch)
time.Sleep(time.Second)
}
func cancle1(ch chan int) {
// 关闭有通道广播的作用,所有消费者都能收到通知,即 <-ch, 拿到对应的类型的零值
close(ch)
}
func cancle2(ch chan int) {
// 只塞了一个值,那么只会有一个消费者拿到数据
ch <- 1
}
func isCancel(ch chan int) bool{
select {
case ret := <-ch:
fmt.Println(ret)
return true
default:
return false
}
}
func TestMyContext(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background()) // 返回上下文和取消上下文的方法
for i:=0 ; i < 5; i++ {
go func(i int, ctx context.Context) {
for {
if isCancelled(ctx) {
break
}
time.Sleep(time.Microsecond * 5)
}
fmt.Println(i, "Cancelled")
}(i, ctx)
}
cancel() // 关闭上下文
time.Sleep(time.Second)
}
func isCancelled(ctx context.Context) bool {
select {
case <-ctx.Done(): // 上下文结束
return true
default:
return false
}
}
func TestSyncOnce(t *testing.T) {
for i:=0; i<3; i++ {
go doOnce() //只会有一个协程执行成功
}
}
func doOnce() {
once.Do(func() {
println("我只能执行一次")
})
}
func TestSyncPoolTest(t *testing.T) {
pool := &sync.Pool{
New: func() interface{
}{
return 0
}}
v := pool.Get().(int)
fmt.Println(v)// 0 默认调用自定义的 new 方法
pool.Put(3) // 优先放在私有变量中
w := pool.Get().(int) // 拿池里面的东西
fmt.Println(w) //3
}
func TestReflect(t *testing.T) {
var s int32
fmt.Println(getType(s))// int
}
func getType(v interface{
}) string {
t := reflect.TypeOf(v) // 返回值是 reflect.Type
switch t.Kind() {
// 获得类型
case reflect.Int32, reflect.Int64:
return "int"
case reflect.Float32, reflect.Float64:
return "float"
default:
return "Unknown"
}
}
type Man struct {
Name string `json:"name"`
Age int64 `json:"age"`
Sons [2]Son
}
type Son struct {
SonName string `json:"son_name"`
SonAge int64 `json:"son_age"`
}
func main() {
man := Man{
}
man.Age = 32
man.Name = "china"
son := Son{
}
son.SonName = "son"
son.SonAge = 2
man.Sons[0] = son
rs, _ := json.Marshal(man)
fmt.Println(string(rs)) // {"name":"china","age":32,"address":"xxx","Sons":[{"son_name":"son","son_age":2},{"son_name":"","son_age":0}]}
}
func TestMyHttp(t *testing.T) {
http.HandleFunc("/", sayHelloName) // 路由
err := http.ListenAndServe(":9000", nil) // 监听服务
if err != nil {
log.Fatal("err", err)
}
}
func sayHelloName(w http.ResponseWriter, r *http.Request) {
_ = r.ParseForm() //先解析才可以获取格式化好的参数, 否则下面打印出来是空map
fmt.Println(r.Form)
}