1. 基础语法

一. 变量定义

package main

import "fmt"

var (
	// 函数外的变量  并非全局变量, 而是包内变量
	aa = 3
	ss = "kkk"
)
// 函数外面 不能用:=定义变量

func variableZeroValue() {
	var a int
	var s string // go语言的变量  在定义的时候就会有一个 初始值
	fmt.Printf("%d  %q\n", a, s)
}

func variableInitialValue() {
	var a, b int = 3, 4
	var s string = "abc"
	fmt.Println(a, b, s)
}

func varibleTypeDeduction() {
	var a, b, c, s = 3, 4, true, "def"
	fmt.Println(a, b, c, s)
}

func variableShorter() {
	a, b, c, s := 3, 4, true, "def" // :=   和 var =   一个意思, 只能在第一次定义变量时用
	b = 5
	fmt.Println(a, b, c, s)
}

func main() {
	fmt.Println("Hello world")
	variableZeroValue()
	variableInitialValue()
	varibleTypeDeduction()
	variableShorter()
	fmt.Println(aa, ss)
}


二. 内建变量类型

  • bool, string
  • (u)int, (u)int8, (u)int16, (u)int32, (u)int64, 带u表示无符号整型
  • uintptr ptr表示指针
  • byte
  • rune 字符型 32位 go中不叫char,优化了char, 避免了很多坑
  • float32, float64
  • complex64, complex128 复数

复数演示

func euler() {
	c := 3 + 4i               //定义复数
	fmt.Println(cmplx.Abs(c)) // 得到5

	fmt.Println(
		cmplx.Exp(1i*math.Pi), // 或者
		cmplx.Pow(math.E, 1i*math.Pi)) // i不会解释为复数, 需要写成1i

	//(-1+1.2246467991473515e-16i) (-1+1.2246467991473515e-16i)
	
	// 去掉尾巴  可以使用 fmt.Printf("%0.3d", cmplx.Exp(1i*math.Pi))
}

go只有强制类型转化

func trangle() {
	var a, b int = 3, 4
	var c int
	c = int(math.Sqrt(float64(a*a + b*b)))  
	fmt.Println(c)
	// 如果写 var c int = math.Sqrt(a*a, b*b)  会失败, go只能强制类型转化, 无法自动转
}

三. 常量和枚举

常量

  • 例如 const filename = "abc.txt"
  • const 类型可以作为各种类型使用
func consts() {
	const filename = "abc.txt"
	const a, b = 3, 4
	var c int
	c = int(math.Sqrt(a*a + b*b))  //const 类型可以作为各种类型使用,这里会作为float 
	fmt.Println(filename, c)
}

枚举

  • 普通枚举类型
  • 自增值枚举类型
func enums() {
	//const(
	//	cpp = 0
	//	java = 1
	//	python = 2
	//	golang = 3
	//)
	// 可以简化为
	const (
		cpp        = iota
		_           //  _表示跳过 1
		python      //2
		golang      //3
		javascript  //4
	)

	fmt.Println(cpp, javascript, python, golang) // 0, 4, 2,3

	// iota更复杂的用法, 可以作为自增值的 种子

	const (
		b        = 1 << (10*iota)
		kb
		mb
		gb
		tb
		pb
	)
	fmt.Println(b, kb, mb, gb, tb, pb) //1 1024 1048576 1073741824 1099511627776 1125899906842624
}

四. 条件语句

if

import (
	"io/ioutil"
	"fmt"
)

func ifexample() {
	const filename = "abc.txt"
	
	// 常规用法
	//contents, err = ioutil.ReadFile(filename)
	//
	//if err != nil {
	//	fmt.Println(err)
	//} else {
	//	fmt.Printf("%s\n", contents)
	//}
	
	
	// if后面可以跟 多个语句的
	// if语句中可以定义变量
	if contents, err := ioutil.ReadFile(filename); err == nil {
		fmt.Println(string(contents))
	} else {
		fmt.Println("cannot print file contents:", err)
	}
	
	// if后的变量只在 if范围内起作用
}

switch

  • switch 会自动break, 如果不想break, 加fallthrough
func grade(score int) string {
	g := ""
	switch {

	case score < 60 && score >= 0:
		g = "F"
	case score < 80:
		g = "C"
	case score < 90:
		g = "B"
	case score <= 100:
		g = "A"
	default:
		panic(fmt.Sprintf("Wrong score: %d", score)) // panic会终断程序的执行, 并报错
	}

	return g
}

func main() {
	fmt.Println(
		grade(0),
		grade(55),
	)
}


五. 循环

  • for 的条件里不加括号
  • for的条件里可以省略初始条件, 结束条件, 递增表达式
sum := 0
for i:= 1; i <= 100; i++ {
    sum += 1
}

实际举例

package main

import (
	"fmt"
	"strconv"
	"os"
	"bufio"
)

func convertToBin(n int) string { //  10进制转2进制
	result := ""
	for ; n > 0; n /= 2 {
		lsb := n%2
		result = strconv.Itoa(lsb) + result
	}

	if result=="" {
		result = "0"
	}
	return result
}


func printFile(filename string) {
	file, err := os.Open(filename)
	if err != nil {
		panic(err)
	}

	scanner := bufio.NewScanner(file)

	for scanner.Scan() {           // 这里的for 没有起始条件和递增条件 只有结束条件  就相当于while  go语言中没有while
		fmt.Println(scanner.Text())
	}
}


func forever() {
	for {           //  没有起始条件, 没有递增条件, 也没有结束条件  相当于死循环
		fmt.Println("abc")
	}
}

func main() {
	fmt.Println(
		convertToBin(5),  // 101
		convertToBin(13), // 1101
		convertToBin(0), // 0
	)

	printFile("abc.txt")
}


六. 函数

  • 函数名在前 , 返回值类型在后, 参数也是如此
  • 可以将函数作为参数
  • 可以返回多个值
  • go没有 默认参数, 可选参数, 重载等复杂操作, 只有可变参数列表...
  • go的匿名函数 就是 直接省略函数名
package main

import (
	"fmt"
	"math"
	"reflect"
	"runtime"
)

func eval(a, b int, op string) (int, error) {//  error返回错误
	switch op {
	case "+":
		return a + b, nil   // nil 是没有被 赋值的变量 函数 类。。。的默认初始值, 类似空指针
	case "-":
		return a - b, nil
	case "*":
		return a * b, nil
	case "/":
		q, _ := div(a, b)  // 有两个返回值, 但只接收一个返回值
		return q, nil
	default:
		return 0, fmt.Errorf(
			"unsupported operation: %s", op)
	}
}

// 带余数的除法
func div(a, b int) (q, r int) {  // 可以返回多值, 并且可以对返回值取名, 编辑器会用改名接收返回值
	return a / b, a % b
}

func apply(op func(int, int) int, a, b int) int {    // 传入参数op  是函数
	p := reflect.ValueOf(op).Pointer()    // 先获取指针
	opName := runtime.FuncForPC(p).Name() // 再拿到函数名
	fmt.Printf("Calling function %s with args "+
		"(%d, %d)\n", opName, a, b)

	return op(a, b)
}

func sum(numbers ...int) int {  // ...参数列表, 可以传任意数量的int
	s := 0
	for i := range numbers {
		s += numbers[i]
	}
	return s
}

func swap(a, b int) (int, int) {
	return b, a
}

func main() {
	fmt.Println("Error handling")
	if result, err := eval(3, 4, "x"); err != nil {
		fmt.Println("Error:", err)
	} else {
		fmt.Println(result)
	}

	q, r := div(13, 3)  // 接收返回值
	fmt.Printf("13 div 3 is %d mod %d\n", q, r)

	fmt.Println("pow(3, 4) is:", apply(
		func(a int, b int) int {    // 使用go语言的 匿名函数
			return int(math.Pow(
				float64(a), float64(b)))
		}, 3, 4))

	fmt.Println("1+2+...+5 =", sum(1, 2, 3, 4, 5))

	a, b := 3, 4
	a, b = swap(a, b)
	fmt.Println("a, b after swap is:", a, b)
}


七. 指针

  • 指针不能运算
  • go的函数参数都是值传递, 想要达到引用传递的效果, 可以使用指针
func swap(a, b *int){
	*a, *b = *b, *a
}

func main() {

    a, b := 3, 4
	swap(&a, &b)
}

交换值有更好的方法

func swap(a, b int) (int, int) {
	return b, a
}

func main() {

    a, b := 3, 4
	b, a = swap(a, b)
}

猜你喜欢

转载自blog.csdn.net/weixin_41207499/article/details/83268403