go入门二
一.流程控制
1.选择结构
if-else:
package main import (
"io/ioutil"
"fmt"
) func main(){
const filename="abc.txt"
//读文件
content,err :=ioutil.ReadFile(filename)
if err !=nil{
fmt.Println(err)
}else{
fmt.Printf("%s\n",content)
} //if也支持如下语法
if content,err :=ioutil.ReadFile(filename);err !=nil{
fmt.Println(err)
}else{
fmt.Printf("%s\n",content)
}
}
switch:
package main import "fmt" //传入成绩,返回评分等级
func grade(score int) string {
//定义字符串
g := ""
//go为switch每一句都加了break
switch {
case score < 0 || score > 100:
g = "输入错误"
case score < 60:
g = "不及格"
case score < 80:
g = "良"
case score < 90:
g = "优"
case score <= 100:
g = "GOOD"
}
//default: "hahah"
return g
} func main(){
fmt.Println(
grade(0),
grade(61),
grade(75),
grade(86),
grade(86),
grade(101), )
}
2.循环结构
for:
package main import (
"fmt"
"time"
) //死循环
func for1(){
for {
fmt.Println("波多野结衣的奶子大大的")
//睡一秒
time.Sleep(1*time.Second)
}
} //有次数的循环
func for2(){
for i :=1;i<10;i++ {
fmt.Println("波多野结衣可以让我幸福死")
} } //有次数的循环加控制
func for3(){
for i :=1;i<10;i++{
if i%5==0{
fmt.Println("我爱苍老师")
}else if i%2==1{
fmt.Println("我爱波多老师")
}else{
fmt.Println("我爱大桥未久")
}
time.Sleep(1*time.Second)
}
} func main(){
//for1()
//for2()
for3()
}
range:
package main
import "fmt"
func main(){
s :="abc"
for i :=range s{
fmt.Printf("下标%d,值=%c\n",i,s[i])
}
//直接都收到
for i,c :=range s{
fmt.Printf("下标%d,值=%c\n",i,c)
}
for _,c :=range s{
fmt.Printf("值=%c\n",c)
}
}
3.跳转语句
continue和break
package main
import "fmt"
func main(){
for i :=0;i<5;i++{
if i==2{
//break是直接打断,continue,跳过
//break
//continue
}
fmt.Println(i)
}
}
goto:
package main
import "fmt"
func main(){
for i :=1;i<5;i++{
fmt.Println(i)
//goto必须跳转到方法内
goto LABEL2
}
fmt.Println("程序结束")
LABEL2:
fmt.Println("程序over")
}
二.函数
1.自定义函数
函数声明格式:
方法名首字母大写是public,方法名首字母小写是private
func 函数名( [参数列表] ) [返回值列表] {
函数体
}
分类:
package main import "fmt" //无参数无返回值
func Test1(){
fmt.Println("公共的")
} //有参数无返回值
func Test2(v1 int,v2 int){
fmt.Println(v1,v2)
} //有不定参数无返回值
func Test3(args ...int){
//这边的前面是索引,后面的是值
for _,n :=range args{
fmt.Println(n)
}
} //无参数有返回值
func Test4()(a int,str string){
a=666
str="喜欢骑苍老师"
return
} func Test5()(int,string){
return 250,"喜欢被苍老师骑"
} //有参数有返回值(求两个数的最大值和最小值)
func Test6(num1 int,num2 int)(min int,max int){
if num1>num2{
min=num2
max=num1
}else{
min=num1
max=num2
}
return }
func main(){
Test1()
Test2(1,2)
Test3()
Test3(1,2,3,4)
fmt.Println(Test4())
fmt.Println(Test5())
fmt.Println(Test6(2,1))
}
例题:求1.。。100的和
package main import "fmt" // 循环实现1到100累加
func Test01() int {
sum := 0
for i := 1; i <= 100; i++ {
sum += i
}
return sum
} //递归实现
//传100
func Test02(num int) int {
if num == 1 {
return 1
}
return num + Test02(num-1)
} func main() {
fmt.Println(Test01())
fmt.Println(Test02(100))
}
2.defer关键字,延迟操作
defer⽤于延迟一个函数或者方法的执行
defer语句经常被用于处理成对的操作,如打开、关闭、连接、断开连接、加锁、释放锁
通过defer机制,不论函数逻辑多复杂,都能保证在任何执行路径下,资源被释放
释放资源的defer应该直接跟在请求资源的语句后,以免忘记释放资源
package main
import "fmt"
func test(x int) {
fmt.Println(100 / x)
}
func main() {
//defer是延迟操作
defer fmt.Println("aaaa")
defer fmt.Println("bbbb")
//报错并不影响程序运行
defer test(0)
defer fmt.Println("cccc")
}
三.复合类型

1.指针
go语言中指针是很容易学习的,比C中容易的多,它可以更简单地执行一些任务
与变量类似,使用前需要声明
声明指针的格式:
var 指针变量名 *指针类型

简单使用:
package main
import "fmt"
func main(){
//声明变量
var a int=10
//声明指针
var p *int
//指针变量储存
p=&a
fmt.Printf("a变量的地址是%x\n",&a)
//指针变量的存储地址
fmt.Printf("p变量的指针地址%x\n",p)
//使用指针访问值
fmt.Printf("*p变量的值是:%d\n",*p)
}
使用指针改变所指向的内存的值
package main
import "fmt"
func main(){
//定义变量
var num int=10
fmt.Println(&num)
//定义指针
var prt *int
//g给指针赋值(指针指向哪个内存地址)
prt=&num
*prt=20
fmt.Println(num) //20
}
值传递和引用传递
go空指针,go空是用nil

答案 3,4
再看几个例子
package main import "fmt" //变量交换
//go方法是值传递
func swap(a,b int){
a,b =b,a
} func main(){
a,b :=3,4
swap(a,b)
fmt.Println(a,b)
}
答案是3,4
package main import "fmt" //go方法参数是值传递
func swap(a,b *int){
*a,*b =*b,*a
} func main() {
a,b :=3,4
//指针是存地址的
swap(&a,&b)
fmt.Println(a,b) }
答案是:4,3
另一种方法
package main import "fmt" //go方法参数是值传递
func swap(a,b int)(int,int){
return b,a
} func main() {
a,b :=3,4
//指针是存地址的
a,b=swap(a,b)
fmt.Println(a,b) }
2.new和make
new()用来分配内存,但与其他语言中的同名函数不同,它不会初始化内存,只会将内存置零
make(T)会返回一个指针,该指针指向新分配的,类型为T的零值,适用于创建结构体
make()的目的不同于new(),它只能创建slice、map、channel,并返回类型为T(非指针)的已初始化(非零值)的值
看一个例子
package main import (
"fmt"
) func main(){
//未初始化
p :=new([] int)
fmt.Println(p) //已经初始化
v:=make([] int,10,50)
fmt.Println(v) //*p[0]=10 会报错,下标越界,未初始化为分配 v[0]=10
fmt.Print(v) }
3.数组
声明数组:
var 数组名[数组长度] 数组类型
声明和初始化数组
数组遍历
数组是值类型还是引用类型?
看一个例子
package main
import "fmt"
func main(){
//1.定义数组
//数组必须制定长度和类型
var arr1[5] int
//:=创建,必须赋值
arr2:=[3] int{1,2,3}
//3省累大小
arr3 :=[...]int{2,3,4,5,}
fmt.Println(arr1,arr2,arr3)
var grid[ 4][5]int
fmt.Println(grid)
//数组遍历
//1.直接遍历
for i:=0;i<len(arr3);i++{
fmt.Println(arr3[i])
}
//2.range
for i,v:=range arr3{
fmt.Println(i,v)
}
}
数组是值传递还是引用传递
package main
import "fmt"
func main(){
//1.定义数组
//数组必须制定长度和类型
var arr1[5] int
//:=创建,必须赋值
arr2:=[3] int{1,2,3}
//3省累大小
arr3 :=[...]int{2,3,4,5,}
fmt.Println(arr1,arr2,arr3)
var grid[ 4][5]int
fmt.Println(grid)
//数组遍历
//1.直接遍历
for i:=0;i<len(arr3);i++{
fmt.Println(arr3[i])
}
//2.range
for i,v:=range arr3{
fmt.Println(i,v)
}
}

数组和列表的区别,有类型,有大小,不可变
使用指针
package main import "fmt" //方法传入数组,修改元素
func printArr(arr *[5] int){
arr[0]=100
for i,v:=range arr{
fmt.Println(i,v)
}
} func main(){
//定义数组
var arr1 [5]int
arr2 := [3]int{1, 2, 3}
arr3 := [...]int{2, 4, 6, 8, 10}
fmt.Println(arr1, arr2, arr3) printArr(&arr1)
//不同长度,不能传参
//printArr(arr2)
printArr(&arr3)
fmt.Println()
fmt.Println(arr1, arr3) }

说明是值传递
4.slice
数组的长度在定义之后无法再次修改,go语言提供了数组切片(slice)来弥补数组的不足
创建切片的各种方式
切片的操作
内建函数append()
内建函数copy()
切片的创建
package main
import "fmt"
func main(){
//声明切片和数组不一样的是不用指定大小
var s1 []int
fmt.Println(s1)
//:声明,必须{},:声明的必须赋值
s2:=[] int{}
fmt.Println(s2)
//make
//诺写一个0.则代表大小和容量都是0
//var s3 [] int=make([] int,0)
//d声明的时候大小为10,存11个也没问题
var s3 [] int=make([] int,10,10)
fmt.Println(s3)
s4 := []int{1, 2, 3}
fmt.Println(s4)
}
切片的操作(取值)
package main
import "fmt"
func main(){
//其切片取值
arr :=[...]int{1,2,3,4,5,6,7}
fmt.Println("arr[2:6]=",arr[2:6])
fmt.Println("arr[:6]=",arr[:6])
fmt.Println("arr[2:]=",arr[2:])
fmt.Println("arr[:]=",arr[:])
}


内建函数append():向切片尾部添加数据
package main
import "fmt"
func main(){
var s1 [] int
s1=append(s1,1)
fmt.Println(s1)
s1=append(s1,2,3)
fmt.Println(s1)
s1=append(s1,4,5,6)
fmt.Println(s1)
//创建指定大小的切片
s2:=make([] int,5)
s2=append(s2,6)
fmt.Println(s2)
//创建并初始化切片
s3:=[]int{1,2,3}
s3=append(s3,4)
fmt.Println(s3)
}
//从这个例子也能看出数组和切片的区别

go语言切片实际上是view操作
package main
import "fmt"
func main() {
//1.go语言切片是对原数组的映射,并没有创建一个真正的切片
// 定义数组
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
//取切片
s1 := arr[2:]
//修改值
s1[0] = 100
fmt.Println(s1)
fmt.Println(arr)
fmt.Println()
// go语言切片没有取到的位置,可以向后延申,不可向前延申
s3 := arr[2:6]
fmt.Println(s3)
s4 := s3[3:5]
fmt.Println(s4)
//容量和大小
fmt.Printf("s3=%v,len(s3)=%d,cap(s3)=%d\n", s3, len(s3), cap(s3))
}

append操作切片
package main
import "fmt"
func main() {
//1.go语言切片是对原数组的映射,并没有创建一个真正的切片
// 定义数组
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
//取切片
s1 := arr[2:6]
fmt.Println(s1)
s2 := s1[3:5]
fmt.Println(s2)
s3 := append(s2,10)
fmt.Println(s3)
fmt.Println(arr)
s4 := append(s3,11)
fmt.Println(s4)
fmt.Println(arr)
s5 := append(s4,12)
fmt.Println(s5)
fmt.Println(arr)
}

5.map
Map 是go内置的数据结构,是一种无序的键值对的集合,可以通过key快速找到value的值
定义Map:
var 变量名 map[key的数据类型] value的数据类型
创建map
初始化map
键值操作
遍历
删除
练习,创建5个方法,创建map,遍历map,删除键值对,修改map,map查询
6.结构体
go语言没有class,只是个结构体struct
结构体定义:
type 结构体名 struct{}
结构体初始化
7.结构体参数
结构体可以作为函数参数传递
四.面向对象
1.简介
go语言对于面向对象的设计非常简洁而优雅
没有封装、继承、多态这些概念,但同样通过别的方式实现这些特性
2.匿名字段
go支持只提供类型而不写字段名的方式,也就是匿名字段,也称为嵌入字段
同名字段的情况
所有的内置类型和自定义类型都是可以作为匿名字段去使用
指针类型匿名字段
3.方法
在面向对象编程中,一个对象其实也就是一个简单的值或者一个变量,在这个对象中会包含一些函数
这种带有接收者的函数,我们称为方法,本质上,一个方法则是一个和特殊类型关联的函数
方法的语法如下
func (接收参数名 接收类型) 方法名(参数列表)(返回值)
可以给任意自定义类型(包括内置类型,但不包括指针类型)添加相应的方法
接收类型可以是指针或非指针类型
为类型添加方法
值语义和引用语义
方法的继承
方法的重写
方法值和方法表达式
练习:创建属性的getter和setter方法并进行调用
4. 包和封装
方法首字母大写:public
方法首字母小写:private
为结构体定义的方法必须放在同一个包内,可以是不同的文件
5.接口
go语言中,接口(interface)是一个自定义类型,描述了一系列方法的集合
接口不能被实例化
接口定义语法如下
type 接口名 interface{}
PS:接口命名习惯以er结尾
接口定义与实现
接口继承
空接口
类型查询
comma-ok断言
switch测试
6.面向对象练习
定义接口IPerson,定义吃喝睡三个抽象方法
定义结构体Person,实现上述方法
定义一个Person的实现类Worker即劳动者,拥有劳动方法Work()(output string)其中output是其工作产出,和休息方法Rest()
继承IWorker实现三个不同职业的子类:程序员Coder、老师Teacher、农民Farmer
创建一个IWorker的数组,将3个实例添加进去
main中测试工作日和周末,输出如下打印
五.异常处理
1.抛异常和处理异常
系统抛
自己抛
2.返回异常
六.处理字符串
go入门二的更多相关文章
- 【原创】NIO框架入门(二):服务端基于MINA2的UDP双向通信Demo演示
前言 NIO框架的流行,使得开发大并发.高性能的互联网服务端成为可能.这其中最流行的无非就是MINA和Netty了,MINA目前的主要版本是MINA2.而Netty的主要版本是Netty3和Netty ...
- Swift语法基础入门二(数组, 字典, 字符串)
Swift语法基础入门二(数组, 字典, 字符串) 数组(有序数据的集) *格式 : [] / Int / Array() let 不可变数组 var 可变数组 注意: 不需要改变集合的时候创建不可变 ...
- Thinkphp入门 二 —空操作、空模块、模块分组、前置操作、后置操作、跨模块调用(46)
原文:Thinkphp入门 二 -空操作.空模块.模块分组.前置操作.后置操作.跨模块调用(46) [空操作处理] 看下列图: 实际情况:我们的User控制器没有hello()这个方法 一个对象去访问 ...
- DevExpress XtraReports 入门二 创建 data-aware(数据感知) 报表
原文:DevExpress XtraReports 入门二 创建 data-aware(数据感知) 报表 本文只是为了帮助初次接触或是需要DevExpress XtraReports报表的人群使用的, ...
- css入门二-常用样式
css入门二-常用样式总结 基本标签样式 背景色background-color 高度height; 宽度width; 边框对齐以及详细设定举例 width/*宽度*/: 80%; height/*高 ...
- 微服务(入门二):netcore通过consul注册服务
基础准备 1.创建asp.net core Web 应用程序选择Api 2.appsettings.json 配置consul服务器地址,以及本机ip和端口号信息 { "Logging&qu ...
- IM开发者的零基础通信技术入门(二):通信交换技术的百年发展史(下)
1.系列文章引言 1.1 适合谁来阅读? 本系列文章尽量使用最浅显易懂的文字.图片来组织内容,力求通信技术零基础的人群也能看懂.但个人建议,至少稍微了解过网络通信方面的知识后再看,会更有收获.如果您大 ...
- 脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?
1.引言 本文接上篇<脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手>,继续脑残式的网络编程知识学习 ^_^. 套接字socket是大多数程序员都非常熟悉的概念,它是计算机 ...
- 2.Python爬虫入门二之爬虫基础了解
1.什么是爬虫 爬虫,即网络爬虫,大家可以理解为在网络上爬行的一直蜘蛛,互联网就比作一张大网,而爬虫便是在这张网上爬来爬去的蜘蛛咯,如果它遇到资源,那么它就会抓取下来.想抓取什么?这个由你来控制它咯. ...
- [转帖]脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?
脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么? http://www.52im.net/thread-1732-1-1.html 1.引言 本文接上篇<脑残式网 ...
随机推荐
- JarvisOJ level3_x64
这一题是和前面x86的差不多,都是利用了同一个知识点,唯一的区别就是使用的堆栈地址不同,x86是直接使用堆栈来传递参数的,而x64不同 x64的函数调用时整数和指针参数按照从左到右的顺序依次保存在寄存 ...
- [LC] 55. Jump Game
Given an array of non-negative integers, you are initially positioned at the first index of the arra ...
- 浏览器证书问题,chorm,ie,edge,safari都会去读系统证书,firefox例外
坑爹 没想过浏览器兼容的问题. 为系统安装用户证书后, firefox一直无法连接 提示 连接 www.httpsserver.com:8985 时发生错误. SSL 对等端无法协商出一个可接受的安全 ...
- windows 不能在本地计算机启动apache2。有关更多信息,查阅系统事件日志。如果这是非Microsoft服务,请与服务厂商联系,并参考特定服务错误代码1
今天使用apache的时候又无法启动了,之前也遇到过,这次重点说这一次的情况,其他情况可以查看博主apache相关的其他博文:网上关于apache服务端的设置的很多,但是都不适合我的情况: 一般使用a ...
- ./config\make\make install命令详解
这些都是典型的使用GNU的AUTOCONF和AUTOMAKE产生的程序的安装步骤 一.基本信息 1../configure 是用来检测你的安装平台的目标特征的.比如它会检测你是不是有CC或GCC,并不 ...
- caffe之mac环境下通过XCode调试C++程序
caffe log输出参考:http://blog.csdn.net/langb2014/article/details/50482150mac下用xcode开发caffe:http://coldmo ...
- SpringSecurity 如何提示错误
1.可以通过authentication-failure-url="/login.html?error=1" 前端接收参数,根据参数提示 错误 2.前端vue this.myNam ...
- Apollo配置中心介绍与使用指南
转载于https://github.com/ctripcorp/apollo,by Ctrip, Inc. Apollo配置中心介绍 Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中 ...
- nginx安装与fastdfs配置--阿里云
上一篇文章:fastDFS 一二事 - 简易服务器搭建之--阿里云 做了fastDFS的服务安装和配置,接下来我们来看nginx的安装 第一步:安装nginx需要安装的一些环境: 1.例如: yum ...
- 850. Dijkstra求最短路 II
给定一个n个点m条边的有向图,图中可能存在重边和自环,所有边权均为正值. 请你求出1号点到n号点的最短距离,如果无法从1号点走到n号点,则输出-1. 输入格式 第一行包含整数n和m. 接下来m行每行包 ...