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的属 ...
随机推荐
- 深度探索MySQL主从复制原理
深度探索MySQL主从复制原理 一 .概要 MySQL Replication (MySQL 主从复制) 是什么? 为什么要主从复制以及它的实现原理是什么? 1.1 MySQL 主从复制概念 MySQ ...
- Disruptor分布式id生成策略
需要的pom文件: <!-- 顺序UUID --> <dependency> <groupId>com.fasterxml.uuid</groupId> ...
- css选择符优先级
- orangepi自启动打开一个终端并且运行脚本
第一步: 在 /home/pi/.config 下创建一个文件夹,名称为 autostart,如果已经存在则不需要创建 第二步: 在autostart文件夹中创建桌面启动项文件,(文件名以 .desk ...
- iPad所有平板型号屏幕尺寸
1.iPad所有平板型号屏幕尺寸 尺寸 iPad型号 物理点 像素点 倍数 7.9 iPad Mini 768x1024 768x1024 1 7.9 iPad Mini 2 iPad Mini 3 ...
- 一段让人瑟瑟发抖的ABAP代码
昨天11月1日是万圣节,Jerry在继续忙着调研SAP Commerce Cloud里的产品主数据管理.晚上回家到SAP国外的社交媒体上一看,好热闹啊.国外的SAP从业者们纷纷以各种各样的方式庆祝万圣 ...
- python 版本号比较 重载运算符
# -*- coding: utf-8 -*- class VersionNum(object): """ 版本号比较 默认版本以“.”分割,各位版本位数不超过3 例一: ...
- Java List<String> list=new ArrayList<String>();为什么要声明为List,而不是ArrayList<String>
例如:代码List list = new ArrayList(); 下面通过list来操作集合.假如代码编写后却发现集合使用的不准确,应该使用LinkedList,那么只要修改一行代码List lis ...
- 【HICP Gauss】数据库 环境的搭建 -1
1.安装规则 1.主机名必须网络唯一 2.主机名必须两位数以上 可以中划线 不能下划线 3.固定IP地址 4.端口号 1888 新增账户 omm 用户组 dbgrp ,家目录 /home/ ...
- WebService接口学习【1】
工具: 1.Eclipse(or)IDEA编辑器 2.SoapUI测试工具 1.wsdl文件标签体的约束: 一:namespace:相当于文件的id 二:targetNamespace属性:用来指定s ...