①
func variableZeroValue(){
var a int //默认值0
var s string //默认值""
fmt.Printf("%d %q\n", a, s)
}
②
func variableInitValue(){
var s int = 3
var s string = "abc"
fmt.Println(a, s)
}
//或者
func variableInitValue(){
var a, b int = 3, 4 //不赋初值也可以
var s string = "abc"
fmt.Println(a, b, s)
}
//不指定类型,会自动辨认类型
③
//写在一行(不需要指定类型,自动辨认类型)
func variableTypeDeduction(){
var a, b, c, s = 3, 4, true, "Hello"
fmt.Println(a, b, c, s)
}
//或者
func variableShorter(){
a, b, c, s := 3, 4, true, "Hello"
b = 5
//第一次=前边一定要有:
//后边=前有:相当于新定义变量
fmt.Println(a, b, c, s)
}
④
//在函数外部,只能用var定义不能用 “:”
//包变量,没有全局变量这种书法
var a = 3
var s = "Hello"
var t = true
//或者
var (
a = 3
s = "Hello"
t = true
)
①需要回顾下复数看这里:
◆例如 $ i = \sqrt{-1} $ 的结果在实数范围内就无法表示,必须借助复数。
◆复数:$ 3 + 4i $
◆$ |3 + 4i| = \sqrt{32+42} = 5 $
◆$ i^2 = -1,i^3 = -i,i^4 = 1 $
◆$ e^{iφ} = cosφ + i sinφ ( 泰 勒 公 式 部 分 ) ◆ (泰勒公式部分) ◆ (泰勒公式部分)◆ |e^iφ| = \sqrt{cos^2φ + sin^2φ} = 1 $
◆$ e^0 = 1, e^{i\dfrac{π}{2}} = i$
◆$ e^{iπ} = -1=>e^{iπ} +1 = 0 (欧拉公式,0/1你懂得,注意), e^{i\dfrac{3π}{2}} = -i, e^{i2π} = 1$
//下面看个复数的例子
func euler(){
c := 3 + 4i//还记得函数里可以用:定义变量吗?3 + 4i会自动识别为复数
fmt.Println(cmplx.Abs(c))//取模,输出5
}
//再看一个欧拉公式的例子
func euler(){
fmt.Println(
cmplx.Exp(1i * math.Pi) + 1//Exp()是e的多少次方,1i是为了让编译器把i识别为复数
//或者
cmplx.Pow(math.E, 1i * math.Pi) + 1)//Pow()是指定底数和指数,输出结果为实部0的数复数
}
//这个因为是float的所以存在误差
//可以用Printf指定为%.3f(根据情况自己调节精度),输出结果为实际想要的
//另外python也是这样,输出结果跟Go一样
②强制类型转换(Go只有强制类型转换,没有隐式类型转换):
直接看个例子:
func triangle(){
//勾股定理,3,4,5
var a, b int = 3, 4
var c int
c = math.Sqrt(a*a + b*b)//错误
c = int(math.Sqrt(float64(a*a + b*b)))//正确
fmt.Println(c)
//Sqrt参数为float64,返回结果为int,输出结果为5
//问题:float在编程语言中是存在误差的,解决方案?
}
☆常量:
◆const filename = “abc.txt”
◆xonst 数值可以作为各种类型使用
◆const a, b = 3, 4(后面用可以不用抢转,自己当所需类型去使用)
func comsts(){
//指定类型,不指定类型都可以
const filename string = "abc.txt"
const a, b = 3, 4
}
func comsts(){
const filename = "abc.txt"
const a, b = 3, 4
var c int//下面需要强制转换
c = int(math.Sqrt(float64(a*a + b*b)))
fmt.Println(filename,c)
}
func comsts(){
const filename = "abc.txt"
const a, b = 3, 4
var c//下面不需要强制转换
c = int(math.Sqrt(a*a + b*b))
fmt.Println(filename,c)
}
func comsts(){
const (
filename = "abc.txt"
a, b = 3, 4
)
var c//下面不需要强制转换
c = int(math.Sqrt(a*a + b*b))
fmt.Println(filename,c)
}
☆枚举
func enums(){
const (
cpp = 0
java = 1
python = 2
golang = 3
javascript = 4
PHP = 5
)
fmt.Println(cpp, java, python, golang, javascript, PHP)
}
//或者
func enums(){
const (
cpp = iota//iota可以自增,是个种子
_
python
golang
javascript
PHP
)
fmt.Println(cpp, _, python, golang, javascript, PHP)
}
//或者
func enums(){
// b kb mb gb tb pb
const (
b = 1 << (10 * iota)
kb
mb
gb
tb
pb
)
fmt.Println(b, kb, mb, gb, tb, pb)
}
if语句:
func main(){
const filename = "abc.txt"
contents, err := ioutil.ReadFile(filename)
if err != nil {
fmt.Println(err)
} else {
fmt.Printf("%s\n", contents)
}
}
//或者
func main(){
const filename = "abc.txt"
if contents, err := ioutil.ReadFile(filename); err != nil{
fmt.Println(err)
} else {
fmt.Printf("%s\n", contents)
}
//出了if语句contents是不能访问的
}
switch语句:(switch会自动break,除非使用fallthrough)
func eval(a, b int, op string) int {//参数名,返回类型
var result int
switch op {
case "+":
result = a + b
case "-":
result = a - b
case "*":
result = a * b
case "/":
result = a / b
default:
panic("unsupported operator:" + op)//中断并打印错误
return result
}
}
//另外一种switch用法:
func grade(score int) string {
switch {
g := ""
case score < 0 || score > 100:
panic("Wrong score:" + score)
case score < 60:
g = "D"
case score < 80:
g = "C"
case score < 90:
g = "B"
case score < 100:
g = "A"
}
return g
}
for循环,没有while:
sum := 0
for i := 1; i <= 100; i++ {
sum += i
}
//for的条件里不需要括号
//for的条件里可以省略初始条件,结束条件,递增条件
//下几个例子
//import也可以用()一块包含进来
import (
"fmt"
"strconv"
)
//省略初始条件
//把一个数转换成二进制
func convertToBin(v int) string {
result := ""
for ; v > 0; v /= 2 {
lsb := v % 2
result = strconv.Itoa(lsb) + result//strconv.Itoa转换string
}
return result
}
// 省略递增条件
func readFile(filename string) string {
file, err := os.Open(filename)
if err != nil {
panic(err)
}
scanner := bufio.NewScanner(file)
for scanner.Scan() {//相当于while
fmt.Println(scanner.Teaxt())
}
}
//省略所有,死循环
for {
//TODO,后期并发编程,通信等等会用到
}
//返回一个值
func eval(a, b int, op string) int {
//TODO
}
//返回两个值或者多个值(返回商和余数)
func div(a, b int) (int int) {
return a / b, a % b
}
//或者
func div(a, b int) (q, r int) {
q = a / b
r = a % b
return
//另外在idea等IDE环境下,如果使用本函数,会自动生成q,r作为返回值接收,这个可以修改
}
/*********************************************/
//Go定义的变量一定要用到,否则编译器会报错
//,当有两个返回值,而又想用其中一个时
//q, _ = div(13, 3)
//return q | 其他操作 即可
/*********************************************/
//还可用于错误返回
func eval(a, b int, op string) (int, error) {
switch op {
case "+":
return a + b, nil
case "-":
return a - b, nil
case "*":
return a * b, nil
case "/":
return a / b, nil
default:
return 0, fmt.Errorf(
"unsupported operator: %s", op)
}
}
提一下函数式编程:
把上边的eval改写下:
func apply(op func(int, int) int,a, b int) int {
return op(a, b)
}
//便于理解,加入辅助代码
func apply(op func(int, int) int,a, b int) int {
p := reflect.ValueOf(op).Pointer()//反射拿到函数指针
opName := runntime.FuncForPC(p).Name()//间接获取名字
fmt.Printf("Calling function %s with args " + "(%d, %d)", opName, a, b)
return op(a, b)
}
可变参数(示例):
fuc sum(numbers ...int) int {
s := 0
for i := range numbers {
s += numbers[i]
}
return s
}
注: 没有函数重载等等比较花哨的方式
var a int = 2
var pa *int = &a
*pa = 3
fmt.Println(a)
★★★(不要害怕,比C简单多了)基本使用跟C、C++一样,但指针不能运算,所以简单
★★★ 如果不使用指针全是值传递
◆数组定义
func main() {
//不赋初值,默认值为0
var arr1 [5]int
//使用:时,必须赋初值
arr2 := [3]int{1, 3, 5}
//如果需要让编译器自动识别长度
arr3 := [...]int{2, 4, 6, 8, 10}
fmt.Println(arr1, arr2, arr3)
//定义一个为维数组,不赋初值默认为0
var grid [4][5]int
fmt.Println(grid)
}
◆数组遍历
//常规做法
for i := 0; i < len(arr3); i++ {
fmt.Println(arr3[i])
}
/*********************/
/*****推荐使用range****/
/******数组是值传递*****/
/*********************/
//或者
for i := range arr3 {//range可以获取数组下标
fmt.Println(arr3[i])
}
//或者
for i, v := range arr3 {//同时获取value属性
fmt.Println(i, v)
}
//或者
for _, v := range arr3 {//同时获取value属性
fmt.Println(v)//只打印值
}
// 官方文档说Slice是一个视图,所以不是值传递
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
s := arr[2:6]//前闭后开
//再看一个例子
func updateSlice(s []int) {
s[0] = 100
}
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
fmt.Println("arr[2:6] = ", arr[2:6])
fmt.Println("arr[:6] = ", arr[:6])
s1 := arr[2:]
fmt.Println("s1 = ", s1)
s2 := arr[:]
fmt.Println("s2 = ", s2)
fmt.Println("After updateSlice(s1)")
updateSlice(s1)
fmt.Println(s1)
fmt.Println(arr)
}
思考一个问题:
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
arr[0], arr[2] = 0, 2
s1 = arr[2:6]
s2 = s1[3:5]
//请问s1, s2分别是?
fmt.Printf("s1=%v, len(s1)=%d, cap(s1)=%d\n", s1, len(s1), cap(s1))
fmt.Printf("s2=%v, len(s2)=%d, cap(s2)=%d\n", s2, len(s2), cap(s2))
切片可以向后扩展,不可以向前!
(持续更新中)