21天从Java转向Go之第三天——初出茅庐
名称
Go中25个关键字 只能在语法允许的地方使用,不能做为名称
- break
- default
- func
- interface
- select
- case
- defer
- go
- map
- struct
- chan
- else
- goto
- pacakage
- switch
- const
- if
- range
- type
- continue
- for
- import
- return
- var
内置的预声明的常量、类型和函数名称。这些名称不是预留的,可以对其重声明,但这会有冲突的风险。
常量
- true false iota nil
类型
- int int8 int16 int32 int64
- uint uint8 uint16 uint32 uint64 uintptr
- float32 float64 complex128 complex64
- bool byte rune string error
函数
- make len cap new append copy close delete
- complex real imag
- panic recover
命名及访问权限
- 在函数体中的声明,只在函数局部有效。
- 声明在函数外的实体,则对相同包里面的所有源文件可见。
- 如果名称开头字母是大写,则是导出的。意味这它对包外是可见和可访问的,可以被自己包之外的其他程序所引用,像fmt包的Printf函数。包名总是小写。
- 这一点简化了像Java的权限修饰符 private protected public。权限以包为单位,不是像Java一样,以类为基础单位。
- go语言的命名本身没有长度限制。Go的编程风格倾向于短名称,特别是作用域较小的局部变量,更喜欢叫i,而不是theLoopIndex。
- 风格上使用驼峰命名,作用域越大,名称命名相应更长更有意义。
声明
- 有四个主要的声明,变量,常量,类型,函数
- Go程序存储在一个或多个以.go为后缀的文件里。每个go文件以package声明开头,表明文件属于哪个包。
- package声明后面是import声明,然后是--包级别--的常量,变量,类型,函数,不区分顺序。
代码说明
package main
//导入包的两种形式 单个导入 多个导入
//导入如果不使用,会报错,需要使用_空标识符匿名导入,会执行包内的init函数
//另外可指定别名,包名是从$GOPATH/src/后开始计算的,使用/进行路径分隔
import (
"fmt"
"os"
)
import (
_ "bufio"
_ "image"
_ "io/ioutil" //从$GOPATH/src/开始
)
//常量的定义,单个定义 多个定义 如果多个,使用const()包起来
const (
LARGE = 42
MID = 40
SMALL = 38
)
const PI = 3.14
//变量的声明 var name type = expression
//类型和表达式可以省略其中一个,不能都省略
//如省略表达式,其初始值是对应类型的零值。
//如果是数字类型,零值是0。如果是string类型,零值是""。
//对于接口和引用类型(slice、map、函数、通道、指针)则是nil。
//如果是数组或结构体复合类型的,其零值是里面元素或者成员的零值。
//如省略类型,会根据表达式推断变量的类型
var name = "Tom"
var age int = 1
var height, weight float32
//忽略类型可以一次性声明多个不同的变量
var x, y, z = "hello", false, 1
var clothingSize, clothingColor = LARGE, "black"
//init函数 类似Java的静态代码块,在包初始化时会被调用
func init() {
height = 178.88
fmt.Printf("my name is %s,height = %v\n", name, height)
}
// People 结构体 类似于Java类
type People struct {
age int
name string
height float32
}
//main方法
func main() {
//main方法执行时传入的参数 args类型是slice切片,第一个元素是程序的名称
//Args hold the command-line arguments, starting with the program name.
args := os.Args
fmt.Println(args)
//
//stdin := os.Stdin
//if all, err := ioutils.ReadAll(stdin); err == nil {
// fmt.Println(all)
//}
//new(T)返回的是*T,该类型对象对应的指针
newP := new(People)
newP.age = 66
newP.height = 155
newP.name = "大爷"
fmt.Println(newP)
//短变量声明,用来初始化局部变量,可同时声明多个不同的变量
m, n := 1, 2
fmt.Println(m, n)
//短变量声明最少得声明一个新变量 open是新声明的,error是重新赋值。
create, err := os.Create("")
open, err := os.Open("")
fmt.Println(create, open, err)
//指针,用来存储一个变量的地址。一个指针,指示值所保存的位置。
//不是所有的值都有地址。但是所有的变量都有地址
// pi := &PI Cannot take the address of 'PI' PI这个常量无法获取地址
//使用指针,可以在无须知道变量名字的情况下,间接读取变量或者更改变量的值。
x := 1
p := &x ////使用&符号取地址 表达式&x(x的地址)获取一个指向整形变量的指针,类型是整形指针*int
fmt.Println(p) //0xc00000a0f0
fmt.Println(*p) //表达式*p获取变量的值
fmt.Println("p != nil:", p != nil) //true
ptr := &x
fmt.Println("p == ptr:", p == ptr) //true
//指针的指针是这个指针变量ptr的地址
i := &ptr
fmt.Println(i) //0xc000006088
//针对指针(变量)的指针取值 是该指针的变量地址值
fmt.Println(*i) //0xc00000a0f0 与p的地址相同
p2 := People{height: 162, name: "大娘"}
fmt.Println(p2)
fmt.Println(height)
fmt.Println(weight)
var p3 People = People{height: 155, name: "大妈", age: 88}
fmt.Println(p3)
fmt.Println(p3.height)
fmt.Println(p3.age)
changePeopleName(&p3) //传入指针,修改了实际对象
changePeopleHeight(p3) //只修改了副本
fmt.Println(p3)
//赋值
q := 1
q++
q += 1
q *= 2
fmt.Println(q) //6
//交换赋值,不需要借助临时变量
x, y := 1, 2
y, x = x, y
fmt.Println(x, y) //2 1
//类型声明
type newFloat32 float32
var s newFloat32 = 1
var g float32 = 1
//fmt.Println(s == g) //不同类型无法比较 Invalid operation: s == g (mismatched types newFloat32 and float32)
//类型转换 如果两个类型具有相同的底层类型 或者 二者都指向相同类型的未命名变量指针,则二者是可以相互转换的(这句话暂且没搞懂)
fmt.Println("类型转换之后相同类型才能判断是否相等:",s == newFloat32(g)) //true 通过类型转换T(x)
//sPtr:=&s
//gPtr:=&g
////fmt.Println(sPtr == gPtr)
////fmt.Println(sPtr == newFloat32(gPtr))
}
//函数的声明 func关键字、函数名称 参数列表、 返回列表(可返回多个值)
func floatToInt(f float64) int {
return int(f)
}
func changePeopleName(ptr *People) {
fmt.Println("Before changePeopleName:", ptr.name)
ptr.name = "你大爷"
fmt.Println("After changePeopleName:", ptr.name)
}
func changePeopleHeight(p People) {
fmt.Println("Before changePeopleHeight:", p.height)
p.height = 226.00
fmt.Println("After changePeopleHeight:", p.height)
}
变量的生命周期
生命周期是指在程序执行过程中变量存在的时间段。
包级别变量的生命周期是整个程序的执行时间。
局部变量有一个动态的生命周期,每次执行声明语句时创建一个新的实体,变量一直生存到变得不可访问,这时它占用的存储空间被回收。函数的参数和返回值也是局部变量,它们在其闭包函数被调用的时候创建。
垃圾回收器如何知道一个变量是否应该被回收?基本思路是每一个包级别的变量,以及每一个当前执行函数的局部变量,可以作为追溯该变量的路径的源头,通过指针和其他方式的引用可以找到变量。如果变量的路径不存在,那么该变量变得不可访问。(可达性分析)
局部变量可在包含它的循环的一次迭代之外继续存活,即使包含它的循环已经返回,它的存在还可能延续。因为变量的生命周期是通过它是否可达来确定的。
包的导入和初始化、作用域
- 包的导入路径从$GOPATH/src开始
- 包的初始化,按照在程序中导入的顺序来进行,依赖顺序优先,每次初始化一个包。如果包p导入了包q,那么先初始化p,后初始化q。main包最后初始化。
- 声明的作用域是指声明在程序文本中出现的区域,是一个编译时属性。变量的生命周期是指变量在程序执行期间能被程序的其他部分所引用的起止时间,是一个运行属性。
21天从Java转向Go之第三天——初出茅庐的更多相关文章
- Java命令学习系列(三)——Jmap
Java命令学习系列(三)——Jmap 2015-05-16 分类:Java 阅读(479) 评论(0) Jmap jmap是JDK自带的工具软件,主要用于打印指定Java进程(或核心文件.远程调试服 ...
- 20145221 《Java程序设计》实验报告三:敏捷开发与XP实践
20145221 <Java程序设计>实验报告三:敏捷开发与XP实践 实验要求 以结对编程的方式编写一个软件,Blog中要给出结对同学的Blog网址 记录TDD和重构的过程,测试代码不要少 ...
- Java连接Oracle数据库的三种连接方式
背景: 这两天在学习Oracle数据库,这里就总结下自己上课所学的知识,同时记录下来,方便整理当天所学下的知识,也同时方便日后自己查询. SQL语句的话,这里我就不多讲了,感觉和其他的数据库(MySQ ...
- Java NIO系列教程(三-十二) Buffer
原文链接 作者:Jakob Jenkov 译者:airu 校对:丁一 Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到 ...
- 学习java之基础语法(三)
学习java之基础语法(三) java运算符 计算机的最基本用途之一就是执行数学运算,作为一门计算机语言,Java也提供了一套丰富的运算符来操纵变量.我们可以把运算符分成以下几组: 算术运算符 关系运 ...
- Java 多线程:锁(三)
Java 多线程:锁(三) 作者:Grey 原文地址: 博客园:Java 多线程:锁(三) CSDN:Java 多线程:锁(三) StampedLock StampedLock其实是对读写锁的一种改进 ...
- Java正则速成秘籍(三)之见招拆招篇
导读 正则表达式是什么?有什么用? 正则表达式(Regular Expression)是一种文本规则,可以用来校验.查找.替换与规则匹配的文本. 又爱又恨的正则 正则表达式是一个强大的文本匹配工具,但 ...
- java之jvm学习笔记三(Class文件检验器)
java之jvm学习笔记三(Class文件检验器) 前面的学习我们知道了class文件被类装载器所装载,但是在装载class文件之前或之后,class文件实际上还需要被校验,这就是今天的学习主题,cl ...
- Java IO流学习总结三:缓冲流-BufferedInputStream、BufferedOutputStream
Java IO流学习总结三:缓冲流-BufferedInputStream.BufferedOutputStream 转载请标明出处:http://blog.csdn.net/zhaoyanjun6/ ...
随机推荐
- 洛谷3973 TJOI2015线性代数(最小割+思维)
感觉要做出来这个题,需要一定的线代芝士 首先,我们来观察这个柿子. 我们将\(B\)的权值看作是收益的话,\(C\)的权值就是花费. 根据矩阵乘法的原理,只有当\(a[i]和a[j]\)都为\(1\) ...
- Mydoom样本分析报告
文件检测 信息 值 文件名 1.virus 文件类型 WIN 32 EXE 文件大小 41664 bytes MD5 3d466b0f8ba9f3fe03e137a34d79f682 SHA-256 ...
- NX CAM 读取加工参数
'取加工几何试图程序组 Function GetGemoGroup_Name(ByVal camObjectTag As NXOpen.Tag) As String Dim theGemoGroupT ...
- NX Open 切削层加载
UF_CUT_LEVELS_load Loads the current cut levels for the specified operation into the data structure ...
- __str__ __repr__区别
当print 实例化对象的时候,可以直接输出__str__ 中的 return结果 在console中 直接输实例对象c 只能输出<__main__.Cycle object at 0x0000 ...
- SpringBoot打包到docker(idea+传统方式)
作者:故事我忘了¢个人微信公众号:程序猿的月光宝盒 目录 1. 方式1.通过idea 远程发布 1.1 修改docker.service文件 1. 进入服务器 2. 修改ExecStart行为下面内容 ...
- 如何再一台电脑上配置多个tomcat同时运行
1.配置运行tomcat 首先要配置java的jdk环境,这个就不在谢了 不懂去网上查查,这里主要介绍再jdk环境没配置好的情况下 如何配置运行多个tomcat 2.第一个tomcat: 找到&qu ...
- UltraSoft - Alpha - Scrum Meeting 7
Date: Apr 22th, 2020. Scrum 情况汇报 进度情况 组员 负责 昨日进度 后两日任务 CookieLau PM 完成课程中心的json格式传递 完成邮箱验证机制 刘zh 前端 ...
- 字符串与模式匹配算法(四):BM算法
一.BM算法介绍 BM算法(Boyer-Moore算法)是罗伯特·波义尔(Robert Boyer)和杰·摩尔(J·Moore)在1977年共同提出的.与KMP算法不同的是,BM算法是模式串P由左向右 ...
- Luogu P1084 疫情控制 | 二分答案 贪心
题目链接 观察题目,答案明显具有单调性. 因为如果用$x$小时能够控制疫情,那么用$(x+1)$小时也一定能控制疫情. 由此想到二分答案,将问题转换为判断用$x$小时是否能控制疫情. 对于那些在$x$ ...