Go奇技淫巧
判断io读取是否结束,尽量用if n==0这种方式,因为可以判断很多种情况
package main
import (
"fmt"
"io"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hello"))
fmt.Println(r.Header)
}
func main() {
resp, err := http.Get("http://www.baidu.com")
if err != nil {
return
}
buf := make([]byte, 4096)
results := ""
for {
n, err := resp.Body.Read(buf)
if n == 0 { //判断io读取是否结束,尽量用if n==0这种方式,因为可以判断很多种情况
break
}
if err != nil && err != io.EOF {
fmt.Println(err)
break
}
results += string(buf[:n])
}
fmt.Println(results)
}
nil是有类型和值得,var *int = nil,它底层数据结构为(*int,data)
接口为nil的充要条件为接口的运行时类型为nil,并且接口的运行时值为nil。这里将运行时的类型赋值为了File类型的指针
var w io.Writer
var f *os.File
w = f
fmt.Println(w == nil) //false
这里为什么是false呢?原因是当File类型的指针赋值给Writer接口时,接口的类型被赋值为File类型的指针,而类型描述符被赋值为nil,而一个接口为nil的充要条件为接口的运行时类型为nil,并且接口的运行时值为nil。这里将运行时的类型赋值为了File类型的指针,因此是false。这显然不符合我们的预期,换种说法,这显然不是我们想要的结果,那我们如何进行更改呢?只需要将f的编译时类型改为io.Writer即可。因为两种类型是相同的,因此w = f进行赋值的时候,并不会改变运行时类型,又因为两个的值都是nil,所以运行时的值为nil,这样的话w == nil 就显然为true了
当将空指针赋值给接口时,接口实例并不等于nil
当把一个空指针对象赋值给一个interface后,再判断!= nil就不再成立了
代码如下
package main
import "fmt"
type Person interface {
Name() string
}
type ChenQiongHe struct {
}
func (t *ChenQiongHe) Name() string {
return "雪山飞猪"
}
func main() {
var test *ChenQiongHe
if test == nil {
fmt.Println("test == nil")
} else {
fmt.Println("test != nil")
}
//将空指针赋值给接口
var person Person = test
if person == nil {
fmt.Print("person == nil")
} else {
fmt.Print("person != nil")
}
}
运行结果
test == nil
person != nil
test本来是nil,赋值给person后居然不能再用nil判断了
解决方法
使用reflect包的IsNil判断,封装为一个能用方法
func IsNil(i interface{}) bool {
vi := reflect.ValueOf(i)
if vi.Kind() == reflect.Ptr {
return vi.IsNil()
}
return false
}
补充知识点:
每当有一个进程启动时,系统会自动打开三个文件:标准输入,标准输出,标准错误--对应三个文件:stdin,stdout,stderr,当运行程序结束,系统自动关闭这三个文件
结构体指针做函数返回值的时候
不能返回局部变量的地址值。局部变量保存在栈帧上,函数调用结束后,栈帧释放,局部变量的地址,不再受系统保护,随时可能分配给其他程序,局部变量的值可以返回
内存对齐优化
https://www.cnblogs.com/sunsky303/p/11315429.html
结构体的地址等于首个元素的地址**
package main
import "fmt"
type Person struct {
name string
sex byte
age int
}
func main() {
p := Person{"Jerry", '0', 26}
fmt.Printf("%p\n", &p) //0xc000004460
fmt.Printf("%p\n", &p.name) //0xc000004460
}
用*加类型去调用结构体函数
package main
import (
"fmt"
)
type N struct {
int
}
func (n N) test() {
fmt.Printf("%p\n%d\n", &n, n)
}
func main() {
var n N = N{2}
fmt.Printf("%p\n%d\n", &n, n)
f1 := N.test
f2 := (*N).test //可用*加类型去调用函数
f1(n)
f2(&n)
}
for;true;{} go里面的while true**
var aa bool = true
c := 0
for ; aa; {
fmt.Print(20)
c++
if c > 10 {
aa = false
}
}
两个函数相同类型相同的条件是拥有相同的形参列表和返回值列表(列表的次序,个数和类型都相同)行参名可以不同,以下两个函数类型是相同的
func add(a,b int) int {
return a+b
}
func sub(x int,y int) (c int){
c = x-y;return c
}
可以通过type定义函数类型,函数类型变量可以作为函数的参数和返回值
type Op func(int,int) int
func add(a, b int) int {
return a+b
}
func do (f Op, a, b int) int{
return f(a, b)
}
func main(){
a:=do(add, 1 ,2)
fmt.print(a)
}
主动调用os.exit(1) defer将不会执行
package main
import "os"
import "fmt"
func main(){
defer func(){
fmt.Println("haha")
}()
os.Exit(1)
} //本函数不会打印haha
defer一般放到错误语句检查之后,尽量不要放到循环语句中,相对于普通的函数调用,defer需要间接的数据结构的支持,相对于普通函数有一定的性能损耗
Go奇技淫巧的更多相关文章
- C#开发奇技淫巧三:把dll放在不同的目录让你的程序更整洁
系列文章 C#开发奇技淫巧一:调试windows系统服务 C#开发奇技淫巧二:根据dll文件加载C++或者Delphi插件 C#开发奇技淫巧三:把dll放在不同的目录让你的程序更整洁 程序目录的整理 ...
- 【CSS进阶】box-shadow 与 filter:drop-shadow 详解及奇技淫巧
box-shadow 在前端的 CSS 编写工作想必十分常见.但是 box-shadow 除去它的常规用法,其实还存在许多不为人知的奇技淫巧. 喜欢 markdown 版本的可以戳这里. box-sh ...
- JS~~~ 前端开发一些常用技巧 模块化结构 &&&&& 命名空间处理 奇技淫巧!!!!!!
前端开发一些常用技巧 模块化结构 &&&&& 命名空间处理 奇技淫巧!!!!!!2016-09-29 17 ...
- MySQL优化的奇技淫巧之STRAIGHT_JOIN
原文地址:http://huoding.com/2013/06/04/261 问题 通过「SHOW FULL PROCESSLIST」语句很容易就能查到问题SQL,如下: SELECT post.* ...
- C++的一个奇技淫巧
C++如何写一个函数,得到一个数组的长度呢? size_t GetArrayLength(int Array []) { return sizeof(Array)/sizeof(Array[0]); ...
- linux奇技淫巧
用着用着就发现,linux的每个命令都是那么的深奥而富有技巧,实用而淫荡..真可谓奇技淫巧.... 初学的真不易掌握... http://www.cnblogs.com/include/archive ...
- Git的奇技淫巧🙈
Git的奇技淫巧
- css中各种居中的奇技淫巧总结
css中各种居中的奇技淫巧总结 第一种,在固定布局中比较常用的技巧设置container的margin:0 auto: 第二种(从布局中入手) css .outer{ height:200 ...
- SVN与TortoiseSVN实战:属性的奇技淫巧(二)
硬广:<SVN与TortoiseSVN实战>系列已经写了七篇,本系列结合TortoiseSVN对SVN中容易被忽视的部分进行了详解. 关于属性的奇技淫巧较多,分为两篇来写,第一篇详见< ...
- SVN与TortoiseSVN实战:属性的奇技淫巧(一)
硬广:<SVN与TortoiseSVN实战>系列已经写了六篇,本系列结合TortoiseSVN对SVN中容易被忽视的部分进行了详解,预计再用三.四篇来结束这个系列. 本篇详解一下SVN的属 ...
随机推荐
- linux系统状态脚本
#!/bin/bashprintf "%10s\n" "##主机名##"printf "%-10s\n" "$(hostname) ...
- DSP未来五大发展趋势
在4G无线通信领域,数据吞吐量已经达到了3G时代的100到1000倍;在多媒体处理器领域,每天都有新的标准涌现出来;在更多其它DSP应用领域,密集的数据处理器需求不断给处理器设计团队带来新的挑战.随着 ...
- C++ 多态详解及常见面试题
今天,讲一讲多态: 多态就是不同对象对同一行为会有不同的状态.(举例 : 学生和成人都去买票时,学生会打折,成人不会) 实现多态有两个条件: 一是虚函数重写,重写就是用来设置不同状态的 二是对象调 ...
- 【C#】课堂知识点#4
1.回顾类中基本结构. 成员分为: a.(数据成员) , b.(方法成员) 数据成员: 字段 方法成员:方法,构造函数,属性,索引器,运算符. 属性的作用: 对字段进行访问提供get,set方法. 类 ...
- Mybatis @One注解使用
@One注解:一对一关联查询
- 记录一次mysql宕机的解决办法
首先先粘贴出来我的错误信息,如下: 2019-07-16T00:53:18.285919Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysq ...
- docker-compose的一些服务一直是restarting
1.查看日志 docker logs jenkins(镜像名字) 1.1 可能权限问题 1.2可能内存问题
- sql server 获取某一字段分组数据的前十条记录
1.sql 语法 select m, n from ( select row_number () over (partition by m order by n desc) rn,--以m分组,分组内 ...
- sqlite移植
编译 # tar xvf sqlite-3.6.16.tar.gz # cd sqlite-3.6.16 # ./configure # ./configure --host=arm-linux -- ...
- 修正DejalActivityView在iOS8之前系统上存在的Bug
DejalActivityView是国外的第三方库,可自定义文本内容和文本长度的菊花转加载指示器效果.该第三方库与其它hud存在不同,能够遮盖键盘:可以自定义遮盖NavigationBar或不遮盖Na ...