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
",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函数

包只初始化 不引用

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

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


func main() {

	
}

 Go中的常量const

  永远只读,不可以被修改

***最后一个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
",goos)

	path := os.Getenv("PATH")
	
	fmt.Printf("Path is %s
" ,path)

}

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

值类型与引用类型

  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 
"
	var str1 = `
	go go go ,
	1231 123
	`
	var b  byte = 'c'
	fmt.Println(str)
	fmt.Println(str1)
	fmt.Println(b) //默认是数字标识
	fmt.Printf("%c
",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
",a) //相应值的默认格式。在打印结构体时
	fmt.Printf("%#v
",b)
	fmt.Printf("%T
",c) //相应值的类型的Go语法表示
	fmt.Printf("90%%
") //百分比
	fmt.Printf("%b
",a) //二进制显示
	fmt.Printf("%f
",199.22) //浮点数显示
	fmt.Printf("%q
","this is a str") //单引号围绕的字符字面值,由Go语法安全地转义
	fmt.Printf("%p
",&a) //打印内存地址

	//将一个int类型转化成str 不能用强制转换

	str := fmt.Sprintf("%d",a)
	fmt.Printf("%q
",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
",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 
",number)
		return
	}

	if result == number{
		fmt.Printf("%d is shuixianhua 
",number)

	}else{
		fmt.Printf("%d is not shuixianhua
" ,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
",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
*/
原文地址:https://www.cnblogs.com/liujiliang/p/8986727.html