Go-day02

时间:2023-03-09 19:52:33
Go-day02

Go程序的基本结构

  ***func init() 会在main函数之前执行

  1.包中的函数调用

    a.同一个包中函数,直接调用

    b.不同包中函数,通过包名+点+函数名进行调用

2.包的访问控制规则

    a.大小写意味着这个函数/变量是可导出的

    b.小写意味着这个函数/变量是私有的,包外部不能访问

练习题一:

  写一个程序,对于给定一个数字n,求出所有两两相加等于n的组合。
  比如: 对于n=5,所有组合如下所示:
    0+5=5
    1+4=5
    2+3=5
    3+2=5
    4+1=5
    5+0=5

package main

import (
"fmt"
) //两个数加和,遍历一个数然后另外一个数就是和减去当前值
func list(n int){
for i := 0; i <= n ; i++ {
fmt.Printf("%d+%d=%d\n",i,n -i ,n)
}
}
func main() {
list(10)
} /*
0+10=10
1+9=10
2+8=10
3+7=10
4+6=10
5+5=10
6+4=10
7+3=10
8+2=10
9+1=10
10+0=10
*/

练习题二:

  包别名的应用,开发一个程序,使用包别名来访问包中的函数?

package main

import(
a "add" //设置别名
) func main () { fmt.Println("result:", a.Name)
fmt.Println("result:", a.age)
}

init的加载顺序

package main

import "fmt"
var a string = "xxxxx" //加载顺序:先初始化全局变量,在初始化init,在执行main
var age int = 100 func init(){
a = "xx"
age = 10
}
func main() {
fmt.Println("a",a,"age",age)
}

main函数引入包的加载顺序(包中导入包):

  程序的初始化和执行都起始于main包。如果main包还导入了其它的包,那么就会在编译时将它们依次导入。有时一个包会被多个包同时导入,那么它只会被导入一次(例如很多包可能都会用到fmt包,但它只会被导入一次,因为没有必要导入多次)。当一个包被导入时,如果该包还导入了其它的包,那么会先将其它包导入进来,然后再对这些包中的包级常量和变量进行初始化,接着执行init函数(如果有的话),依次类推。等所有被导入的包都加载完毕了,就会开始对main包中的包级常量和变量进行初始化,然后执行main包中的init函数(如果存在的话),最后执行main函数

Go-day02

包只初始化 不引用

_操作其实是引入该包,而不直接使用包里面的函数,而是调用了该包里面的init函数。
package main

import (
_ "fmt" //下划线加空格 只初始化 不引用
) func main() { }

Go中的常量const

  永远只读,不可以被修改

Go-day02

***最后一个const c = getValue()是不可以的,因为函数的返回值不确定

练习:

  定义两个常量Man=1和Female=2,获取当前时间的秒数,如果能被Female整除,则在终端打印female,否则打印man

package main

import (
"time"
"fmt"
) const (
Man = 1
Female = 2
) func main() { Second := time.Now().Unix()
if (Second % Female == 0){
fmt.Println("female",Female)
}else {
fmt.Println("man",Man)
} }

Go变量

  1.int初始值为0

  2. string初始值为""

3.bool初始值为false

练习:

  获取操作系统和path

package main

import (
"os"
"fmt"
) func main(){
var goos string = os.Getenv("GOOS") fmt.Printf("The operating system is %s\n",goos) path := os.Getenv("PATH") fmt.Printf("Path is %s\n" ,path) }

32位操作系统指针是4字节,64位操作系统指针是8字节

值类型与引用类型

Go-day02

  1.值类型,int,float,bool,string,数组和struct(结构体)

  2.引用类型,指针,slice(切片),map,chan都是引用类型

package main

import (
"fmt"
)
func main() {
a := 5
b := make(chan int,1)
fmt.Println("a= ",a)
fmt.Println("b= ",b)
} /*
a= 5
b= 0xc420050070
*/

练习:

package main

import (
"fmt"
) func modify(a int){
a = 10 //函数属于值类型
return
}
func modify1(p *int) {
*p = 100
//指针是引用类型 所有会改变
}
func main() {
a := 5
b := make(chan int,1)
fmt.Println("a= ",a)
fmt.Println("b= ",b)
modify(a)
fmt.Println("a= ",a)
modify1(&a)
fmt.Println("a= ",a)
} /* a= 5
b= 0xc420050070
a= 5
a= 100
*/

练习:

  将first和second值交换(通过指针改变内存地址后的源数据)

package main

import (
"fmt"
) func swap(a *int,b *int){
tmp := *a
*a = *b
*b = tmp } func main() {
first :=100
second :=200
swap(&first,&second)
fmt.Println("first= ",first)
fmt.Println("second= ",second) } /*
first= 200
second= 100
*/

第二种方法:

package main

import (
"fmt"
) func swap1(a int,b int) (int,int) {
return b,a
} func main() {
first :=100
second :=200
//swap(&first,&second)
first,second = swap1(first,second)
fmt.Println("first= ",first)
fmt.Println("second= ",second) } /*
first= 200
second= 100
*/

局部变量和全局变量使用

package main
import (
"fmt" ) var a string = "M" //定义了个全局变量 func main() {
a := "G" //局部变量
fmt.Println("from main",a) //找自己的局部变量
f1()
}
func f2() {
fmt.Println("from f2",a) //局部变量没有,找全局的a
} func f1(){
a:="O"
fmt.Println("from f1",a)
f2()//执行f2函数相当于重新引用不会继承自己的局部变量
}
/*GOM*/

***重点观察

package main
import (
"fmt" ) var a = "G" func main() {
n()
m()
n() } func n (){
fmt.Println(a)
} func m (){
a = "O" //将a赋值成O,因为m中未定义a所以修改的是全局的a
fmt.Printf(a)
} /*
GOO
*/

 ***重点观察

package main
import (
"fmt" ) var a string //定义了个全局变量 func main() {
a = "G" //局部变量,因为当前未生命a变量,所以修改的是全局的a
fmt.Println("from main",a) //找自己的局部变量
f1()
}
func f2() {
fmt.Println("from f2",a) //局部变量没有,找全局的a,这是全局的a已经被更改为G
} func f1(){
a:="O" //重新在函数内声明var a string = "O"
fmt.Println("from f1",a)
f2()//执行f2函数相当于重新引用不会继承自己的局部变量
} /*
GOG
*/

数据类型和操作符

  1.int8和uint8的区别?

    uint8是无符号int,比int少一位 符号如:"+","-"

  2.不同类型可以转换例子如下:

package main

import (
"fmt"
) func test() { var a int8 = 100
var b int16 = int16(a) //将a的int8转换成int16赋值给b
fmt.Printf("a=%d , b=%d" , a,b)
} func main() {
test()
}

  3.int32是4字节,int64是8字节

练习

  使用math/rand生成10个随机整数,10个小于100的随机整数,10个随机浮点数

package main

import (
"math/rand"
"fmt"
"time"
) func init(){
//放到初始化里
rand.Seed(time.Now().UnixNano()) //以时间戳做为当前随机数的种子,Nano是纳秒
}
func main() { for i := 0 ; i < 10 ; i++ {
a := rand.Int() //获取整数
fmt.Println(a)
}
for i := 0 ;i < 10 ; i++{
a := rand.Intn(100) //获取100以内的随机整数
fmt.Println(a)
}
for i := 0 ; i < 10 ; i++ {
a := rand.Float32() //获取浮点数
fmt.Println(a)
}
}

字符和字符串

  1.字符byte var a  byte = 'c' 一个byte占用1个字节 8位 ***字符必须是单引号

  2.字符串由多个字符组成

3.字符串""与``的区别

    ``可以保存原有格式原封不动打印

package main

import "fmt"

func main() {
var str = "hello world \n"
var str1 = `
go go go ,
1231 123
`
var b byte = 'c'
fmt.Println(str)
fmt.Println(str1)
fmt.Println(b) //默认是数字标识
fmt.Printf("%c\n",b) //字符格式化输出 } /*
hello world go go go ,
1231 123 99
c */

fmt格式化输出详解

/*
一般: %v 相应值的默认格式。在打印结构体时,“加号”标记(%+v)会添加字段名
%#v 相应值的Go语法表示
%T 相应值的类型的Go语法表示
%% 字面上的百分号,并非值的占位符
布尔: %t 单词 true 或 false。
整数: %b 二进制表示
%c 相应Unicode码点所表示的字符
%d 十进制表示
%o 八进制表示
%q 单引号围绕的字符字面值,由Go语法安全地转义
%x 十六进制表示,字母形式为小写 a-f
%X 十六进制表示,字母形式为大写 A-F
%U Unicode格式:U+1234,等同于 "U+%04X"
浮点数及其复合构成: %b 无小数部分的,指数为二的幂的科学计数法,与 strconv.FormatFloat
的 'b' 转换格式一致。例如 -123456p-78
%e 科学计数法,例如 -1234.456e+78
%E 科学计数法,例如 -1234.456E+78
%f 有小数点而无指数,例如 123.456
%g 根据情况选择 %e 或 %f 以产生更紧凑的(无末尾的0)输出
%G 根据情况选择 %E 或 %f 以产生更紧凑的(无末尾的0)输出
字符串与字节切片: %s 字符串或切片的无解译字节
%q 双引号围绕的字符串,由Go语法安全地转义
%x 十六进制,小写字母,每字节两个字符
%X 十六进制,大写字母,每字节两个字符
指针: %p 十六进制表示,前缀 0x */ package main import "fmt" func main() {
var a int = 100
var b bool
c := 'a' fmt.Printf("%v\n",a) //相应值的默认格式。在打印结构体时
fmt.Printf("%#v\n",b)
fmt.Printf("%T\n",c) //相应值的类型的Go语法表示
fmt.Printf("90%%\n") //百分比
fmt.Printf("%b\n",a) //二进制显示
fmt.Printf("%f\n",199.22) //浮点数显示
fmt.Printf("%q\n","this is a str") //单引号围绕的字符字面值,由Go语法安全地转义
fmt.Printf("%p\n",&a) //打印内存地址 //将一个int类型转化成str 不能用强制转换 str := fmt.Sprintf("%d",a)
fmt.Printf("%q\n",str) } /*
result:
100
false
int32
90%
1100100
199.220000
"this is a str"
0xc42007e008
"100" */

用Go实现字符串反转

package main

import "fmt"

func reverse(str string) (string){
var result string
strLen := len(str)
for i := 0 ; i < strLen; i++ {
result = result + fmt.Sprintf("%c",str[strLen -i -1])
}
return result
} func main() {
myStr:= "hello world"
result := reverse(myStr)
fmt.Println(result)
} /*
dlrow olleh
*/

 通过数组反转

package main

import "fmt"

func reverse_arry(str string) (string){
var result []byte //定义一个空数组
length := len(str)
for i := 0 ; i < length ; i++ {
result = append(result,str[length -i -1]) //通过append往数组里追加值
}
return string(result) //最后在string化
} func main() {
myStr:= "hello world"
result = reverse_arry(myStr)
fmt.Println(result)
}

Go的字符串操作

package main

import "fmt"

func main() {
str := "hello"
str1 := "world" //result := str + " " +str1
result := fmt.Sprintf("%s %s", str, str1) //字符串拼接
q := result[6:] //字符串切片
fmt.Println(result)
fmt.Println(q)
} /* hello world
world
*/

练习:

  求100到200的素数,用户随便输入

package main

import (
"fmt"
"math"
) func isPrime(n int ) bool{ for i := 2 ; i < int(math.Sqrt(float64(n))) ; i++ { //素数是大于1的自然数除了1和他本身不能有其他整除,类似于奇数
if n % i == 0 {
return false
} }
return true
} func main() {
var n int
var m int
fmt.Scanf("%d%d",&n,&m) //类似于python的input输入,传入Scanf函数是指针,这样就可以确保函数外定义的变量可以修改值 for i := n ; i < m ; i++ {
if isPrime(i) == true{
fmt.Printf("%d\n",i)
continue
}
} }

   打印出100-999中所有的“水仙花数”,所谓“水仙花数”是指一个三位数,其各位数字立方和等于该数本身。例如:153 是一个  “水仙花数”,因为 153=1 的三次方+5 的三次方+3 的三次方

package main

import "fmt"

func isNumber(num int) bool{
a := num % 10
b := (num / 10) % 10
c := (num / 100) % 10
res := a*a*a + b*b*b + c*c*c
return res == num
} func main() {
var n int
var m int
fmt.Scanf("%d%d",&n,&m)
for i := n ; i < m ; i ++ {
if isNumber(i) == true{
fmt.Println("this is a shuixianhua = ",i)
}
}
} /*
1 999
this is a shuixianhua = 1
this is a shuixianhua = 153
this is a shuixianhua = 370
this is a shuixianhua = 371
this is a shuixianhua = 407
*/

通过ascii码实现水仙花:

package main

import (
"fmt"
"strconv"
) func main() {
var str string
fmt.Scanf("%s" ,&str) var result = 0
for i := 0 ; i < len(str) ; i++ {
sum := int(str[i] - '0') //字符串切片默认是ascii码,通过ascii与0做运算 0代表48(十进制),1代表49(十进制)做差仍为1
result += (sum * sum * sum)
} number,err := strconv.Atoi(str) //将字符串转化为int
if (err != nil) {
fmt.Printf("cat not convert %s to int \n",number)
return
} if result == number{
fmt.Printf("%d is shuixianhua \n",number) }else{
fmt.Printf("%d is not shuixianhua\n" ,number)
} }

对于一个数n,求n的阶乘之和,即: 1! + 2! + 3!+...n!

package main

import "fmt"

func sum(n int ) uint64{
var s uint64 = 1
var sum uint64 = 0
for i := 1; i <= n ; i++ {
s = s * uint64(i) //和乘以当前值 就是下一位阶乘的结果
fmt.Printf("%d!=%v\n",i,s)
sum += s //这是阶乘的和
}
return sum
} func main() {
var n int fmt.Scanf("%d", &n) s := sum(n)
fmt.Println(s) } /*
10
1!=1
2!=2
3!=6
4!=24
5!=120
6!=720
7!=5040
8!=40320
9!=362880
10!=3628800
4037913
*/