Golang学习(用代码来学习) - 第二篇
type Circle struct {
radius float64
desc string
}
//定义结构体里面的方法
func (c Circle) getArea() float64 {
return 3.14 * c.radius * c.radius
}
//如果想要改变结构体里面的成员变量,就必须传入指针,否则的话是不生效的
func (c *Circle) setRadius(val float64) {
c.radius = val
}
//因为没有传入指针,所以这里的Circle对象被拷贝了,因此不生效
func (c Circle) setRadiusFake(val float64) {
c.radius = val
}
/*
方法学习,其实就是类似于类里面的函数,但是go没有类这个东西
*/
func method_test() {
print_start_seperator("method_test");
var cir Circle;
cir.radius = 12;
fmt.Printf("circle's area:%f \n", cir.getArea())
cir.setRadius(10)
fmt.Printf("after real setRadius[%f] circle's area:%f \n", cir.radius, cir.getArea())
cir.setRadiusFake(20)
fmt.Printf("after fake setRadius[%f] circle's area:%f \n", cir.radius, cir.getArea())
print_end_seperator();
}
/**
没有指定大小,是切片,在go里面是指针传递
*/
func slice_func(arr []int) {
for idx, val := range arr {
fmt.Printf("[slice_func]idx:%d val:%d \t", idx, val)
}
fmt.Println("")
}
/**
指定了大小,是数组,在go里面是值传递
*/
func arr_func(arr [5]int) {
for idx, val := range arr {
fmt.Printf("[arr_func]idx:%d val:%d \t", idx, val)
}
fmt.Println("")
}
/**
修改array里面的值,由于数组是值传递,因此这里对原有的参数没有任何影响
*/
func change_arr(arr [5]int, val int) {
for idx, _ := range arr {
arr[idx] = val * 10
}
}
/**
切片是指针传递,因此这里的修改对原有值会有影响
其实本质上这样的写法,切片也是值传递,只是因为在go中切片存储的结构体里面具体的数值是个指针,所以值传递
也只是拷贝了这部分指针的地址,修改的是同一片内存,go中的切片存储的方式如下:
type Slice struct{
arr *int
size int
cap int
}
*/
func change_slice(arr []int, val int) {
for idx, _ := range arr {
arr[idx] = val * 10
}
}
/**
工具函数,打印数组
*/
func print_arr(arr [5]int) {
for _, val := range arr {
fmt.Printf("%d\t", val)
}
fmt.Println("")
}
/**
工具函数,打印切片
*/
func print_slice(arr []int) {
if nil == arr {
return
}
for _, val := range arr {
fmt.Printf("%d\t", val)
}
fmt.Println("")
}
/**
工具函数,打印切片
*/
func print_slice_str(arr []string) {
if nil == arr {
return
}
for _, val := range arr {
fmt.Printf("%s\t", val)
}
fmt.Println("")
}
/*
数组和切片学习,数组和切片在go中是两种完全不同的类型,不要搞混了。
*/
func array_slice_test() {
print_start_seperator("array_slice_test")
arr := []int{5, 4, 3, 2, 1}
slice_func(arr)
//没有指定大小的参数只能传给没有指定大小的函数
//arr_func(arr)
arr2 := [5]int{10, 9, 8, 7, 6}
//slice_func(arr2)
arr_func(arr2)
//下面的数组虽然只是声明,因为指定了大小,所以默认初始化为0
var arr3 [5]int
for _, val := range arr3 {
fmt.Printf("val:%d \t", val)
}
fmt.Println()
//没有指定大小,是切片,在go里面和数组是完全不同的类型,所以arr3本质上是nil,for循环将不会执行
var arr4 []int
for _, val := range arr4 {
fmt.Printf("%d", val)
fmt.Println("I am not executed!!!!")
}
if nil == arr4 {
fmt.Println("arr4 is a nil!!!!!!!!!!!!!")
}
//数组是值传递
var arr5 [5]int = [5]int{0, 0, 0, 0, 0}
change_arr(arr5, 15)
fmt.Println("After changing the array...")
print_arr(arr5)
/**
本质上切片也是值传递,只是因为在go中切片存储的结构体里面具体的数值是个指针,所以值传递
也只是拷贝了这部分指针的地址,修改的是同一片内存,go中的切片存储的方式如下:
type Slice struct{
arr *int
size int
cap int
}
*/
var arr6 []int = []int{0, 0, 0, 0, 0, 0, 0}
change_slice(arr6, 15)
fmt.Println("After changing the slice...")
print_slice(arr6)
//使用数组进行切片的初始化
var arr7 = [5]string{"one", "two", "three", "four", "five"}
slice1 := arr7[:]
print_slice_str(slice1)
slice1 = arr7[1:3]
print_slice_str(slice1)
//slice获取的是原来数组的一段数组引用,因此这里的修改会在原数组上面体现到
slice1[0] = "new_two"
fmt.Printf("After assign to slice. arr7:%s slice1:%s\n", arr7, slice1) //After assign to slice. arr7:[one two new_two four five] slice1:[two new_two]
//此时如果修改原数组呢?
arr7[1] = "newer_two"
//此时切片也生效了,也就是说,他们始终引用的是同一片地址
fmt.Printf("After assign to origin arr. arr7:%s slice1:%s\n", arr7, slice1) //After assign to origin arr. arr7:[one newer_two three four five] slice1:[newer_two three]
//第一个参数为size,第二个参数为capacity
var slice2 = make([]int, 3, 10)
fmt.Printf("slice2. size:%d cap:%d\n", len(slice2), cap(slice2))
//可以通过append来增加slice的数据,记住,这里要接受返回的值
slice2 = append(slice2, 1)
slice2 = append(slice2, 2, 3, 4)
fmt.Printf("After append. slice2:%d\n", slice2) //[0 0 0 1 2 3 4]
//注意append函数是生成了一个新得切片,原来得切片对象不会有任何改变
slice2_bak := append(slice2, 10, 11, 12)
fmt.Printf("After append. slice2:%d slice2_bak:%d\n", slice2, slice2_bak) //After append. slice2:[0 0 0 1 2 3 4] slice2_bak:[0 0 0 1 2 3 4 10 11 12]
var slice3 = make([]int, len(slice2), cap(slice2))
copy(slice3, slice2)
fmt.Printf("After copy slice. slice3:%d\n", slice3)
//注意,一定要指明slice的长度,否则copy将没有任何效果
var slice4 []int
copy(slice4, slice2)
fmt.Printf("After copy slice. slice4:%d\n", slice4) //[]
slice_append()
print_end_seperator()
}
/**
slice里面一个需要注意的现象
*/
func slice_append() {
//注意,这里指定了slice的cap为10
slice := make([]int, 5, 10)
for i := 0; i < 5; i++ {
slice[i] = i
}
slice1 := slice
slice_p := &slice
fmt.Printf("slice:%d slice1:%d slice_p:%d\n", slice, slice1, *slice_p)
fmt.Printf("slice's addr:%p \n", &slice)
//接下来修改slice, 由于slice的cap为10,这里长度够,所以并没有申请新的内存,所以这里slice里面的数组地址没有变化,slice本身也不会变化
slice = append(slice, 10, 11, 12)
fmt.Printf("After append. slice:%d slice1:%d slice_p:%d\n", slice, slice1, *slice_p)
fmt.Printf("After append, slice's addr:%p \n", &slice)
//注意,这里指定了slice的cap为6
slice2 := make([]int, 5, 6)
for i := 0; i < 5; i++ {
slice2[i] = i
}
slice3 := slice2
slice2_p := &slice2
fmt.Printf("slice2:%d slice3:%d slice2_p:%d\n", slice2, slice3, *slice2_p)
fmt.Printf("slice2's addr:%p \n", &slice2)
//接下来修改slice, 由于slice的cap为6,长度不够了,所以会申请新的内存,此时注意,只是slice结构体里面的数组地址发生了变化
//但是对于slice这个结构体本身,其地址并没有发生变化,所以看到的地址也没有变
fmt.Printf("slice.size:%d slice.cap:%d\n", len(slice2), cap(slice2))
slice2 = append(slice2, 10, 11, 12, 13, 14, 15, 16, 17)
fmt.Printf("After append. slice2:%d slice3:%d slice2_p:%d\n", slice2, slice3, *slice2_p)
fmt.Printf("After append, slice2's addr:%p \n", &slice2)
}
Golang学习(用代码来学习) - 第二篇的更多相关文章
- Golang学习(用代码来学习) - 第一篇
package main import ( "fmt" "time" "unsafe" ) //示例代码 var isActive bool ...
- 学习KnockOut第二篇之Counter
学习KnockOut第二篇之Counter 欲看此 ...
- 老老实实学习WCF[第二篇] 配置wcf
老老实实学WCF 第二篇 配置WCF 在上一篇中,我们在一个控制台应用程序中编写了一个简单的WCF服务并承载了它.先回顾一下服务端的代码: using System; using System.Col ...
- 从别人的代码中学习golang系列--01
自己最近在思考一个问题,如何让自己的代码质量逐渐提高,于是想到整理这个系列,通过阅读别人的代码,从别人的代码中学习,来逐渐提高自己的代码质量.本篇是这个系列的第一篇,我也不知道自己会写多少篇,但是希望 ...
- 从别人的代码中学习golang系列--03
这篇博客还是整理从https://github.com/LyricTian/gin-admin 这个项目中学习的golang相关知识. 作者在项目中使用了 github.com/casbin/casb ...
- RabbitMQ学习总结 第二篇:快速入门HelloWorld
目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...
- #Java学习之路——基础阶段二(第二篇)
我的学习阶段是跟着CZBK黑马的双源课程,学习目标以及博客是为了审查自己的学习情况,毕竟看一遍,敲一遍,和自己归纳总结一遍有着很大的区别,在此期间我会参杂Java疯狂讲义(第四版)里面的内容. 前言: ...
- 20172327 2018-2019-1 《第一行代码Android》第二章学习总结
学号 2017-2018-2 <第一行代码Android>第二章学习总结 教材学习内容总结 - 活动是什么: 活动(Activity)是最容易吸引用户的地方,它是一种可以包含用户界面的组件 ...
- angularjs学习第三天笔记(过滤器第二篇---filter过滤器及其自定义过滤器)
您好,我是一名后端开发工程师,由于工作需要,现在系统的从0开始学习前端js框架之angular,每天把学习的一些心得分享出来,如果有什么说的不对的地方,请多多指正,多多包涵我这个前端菜鸟,欢迎大家的点 ...
- JavaWeb学习总结第二篇--第一个JavaWeb程序
JavaWeb学习总结第二篇—第一个JavaWeb程序 最近我在学院工作室学习并加入到研究生的项目中,在学长学姐的带领下,进入项目实践中,为该项目实现一个框架(用已有框架进行改写).于是我在这里记录下 ...
随机推荐
- Java中Stream流相关介绍
什么是Stream? Stream是JDK8 API的新成员,它允许以声明性方式处理数据集合 特点 代码简洁: 函数式编程写出的代码简洁且意图明确,使用stream接口让你从此告别for循环 多核友好 ...
- [C] gcc
概述 GNU C Compiler 流程 预处理,生成.i文件(中间文件,看不到) 编译,生成.s文件(中间文件,看不到) 汇编,生成.o文件 链接,生成可执行文件 参数 -E:预处理 -S:预处理, ...
- [转载]备忘:oh my zsh 的安装、更新、删除
备忘:oh my zsh 的安装.更新.删除 傅易君 关注 0.8 2016.09.25 00:56* 字数 68 阅读 14920评论 0喜欢 4 查看系统当前 shell $ cat /etc/ ...
- 联想 lenove 3750 M4服务器更改启动项和管理口IP
联想 lenove 3750 M4服务器更改启动项和管理口IP 注: 因为在机房拍照的原因,再加上工作比较忙:整理成文档的时候有的过程已经忘记了,所以有的步骤可能会缺失,里面的选项都已经用中文方式表达 ...
- Mysql 数据库基本操作
1.数据库设置密码 [root@db02 scripts]# mysqladmin -uroot password 123 2.使用密码登录 #1.正确的方式(不规范) [root@db02 scri ...
- 5.1-5 uname、hostname、dmesg、stat、du
5.1 uname:显示系统信息 uname命令用于显示系统相关信息,比如内核版本号.硬件架构等. -a 显示系统所有相关信息 -v 显示内核版本 -m 显示计算机硬件架构 ...
- docker存储驱动
http://www.sohu.com/a/101016494_116235 https://success.docker.com/article/compatibility-matrix Red H ...
- Jenkins 基础篇-凭证配置
我们在正式开始使用 Jenkins 之前还要先配置一些凭证,这些凭证的作用主要是用于认证,例如我们要从代码仓库拉取代码,就需要用到代码仓库的账号密码或者密钥:我们要登录远程服务器也需要用户名密码或者密 ...
- SSTI漏洞-fastapi
0x00 原理 SSTI漏洞全称服务器模板注入漏洞,服务器模板接收了用户输入的恶意代码,未经过滤便在服务端执行并通过渲染模板返回给用户,使得用户可以通过构造恶意代码在服务端执行命令. 0x01 c ...
- Jmeter- 笔记4 - 参数化 、函数
参数化 调用变量的用法: ${变量名} 参数化第一 二种. 定义变量的两种方法: 配置元件(Config Element) -> 用户定义的变量(User Defined Variables) ...