经常会有一些朋友问go语言的一些问题和疑惑,其实好多问题在官方文档和stackoverflow里都有详细的讲解,只要你肯花时间读一遍官方文档Effective Go基本上都有找到答案。本文总结一下大家经常问到的一些问题,长期更新。

  代码都在github上, 地址 https://github.com/lpxxn/gocommonquestions

new 和make 的区别

  简单来说,new(T)用于分配内存,返回指向T类型的一个指针,指针的值为T类型的零值

    n1 := new(int)
fmt.Println(n1) // console the address of n1
fmt.Println(*n1 == ) // zero value type T struct {
I int
A string
Next *T
}
n2 := new(T)
fmt.Println(n2)
fmt.Println(n2.I == )
fmt.Println(n2.Next == nil)
fmt.Println(n2.A == "") n3 := new([]int)
fmt.Println(n3)
fmt.Println(*n3 == nil)

  make(T)   只能用于slice、map和channel, 返回非零值的T。

    m1 := make([]int, )
fmt.Println(m1)
m2 := make(map[int]string)
m2[] = "abcde"
m3 := make(chan int) m4 := make(chan int, )

  make 返回的是类型本身,new 返回的是指向类型的指针

相关讲解

https://stackoverflow.com/questions/9320862/why-would-i-make-or-new

https://golang.org/doc/effective_go.html#allocation_new

https://golang.org/ref/spec#The_zero_value

是否需要主动关闭channel

  除非你的程序需要等待channel关闭后做一些操作,不用主动去关闭channel。当没有地方在使用这个channel的时候go的垃圾回收系统会自动回收,如果channel里还有值,但是没有地方引用了,也会被回收。

  下面的小例子就是在等待channel c1和c2关闭后,再做一些事情。  

func main() {
c1 := make(chan int, )
go test1(c1)
for v := range c1 {
fmt.Println(v)
} fmt.Println("after close c1 do something")
c2 := make(chan bool)
go func() {
time.AfterFunc(time.Second * , func() {
close(c2)
})
}()
_, close := <- c2
if !close {
fmt.Println("after c2 closed do something")
} fmt.Println("end")
} func test1(c chan<- int) {
for i := ; i < ; i++ {
c <- i
}
close(c)
}

简单测试垃圾回收channel

func createChan() chan int64{
c := make(chan int64, )
c <-
return c
} func main() { RM()
for i := ; i < ; i++ {
c := createChan()
c <-
RM()
runtime.GC()
}
RM()
} func RM(){
var m runtime.MemStats
runtime.ReadMemStats(&m)
fmt.Println(m.Alloc)
}

  

相关讲解:https://stackoverflow.com/questions/8593645/is-it-ok-to-leave-a-channel-open

https://groups.google.com/forum/#!msg/golang-nuts/pZwdYRGxCIk/qpbHxRRPJdUJ

https://groups.google.com/forum/#!topic/golang-nuts/KtIyc5lTRJY

Unbuffered channel和buffered channel 区别

buffered channel

c3 := make(chan bool, )  // buffered channel

buffered channel 可以持续的发送数据到channel,直到channel满为至。不用等待是否有接收channel。

如果channel满了,会等待读取channel,当有channel被读取,就会继续发送数据到channel

    c3 := make(chan bool, )  // buffered channel

    go func() {
for i := ; i < ; i++ {
c3 <- i % ==
}
close(c3)
}() for v := range c3 {
fmt.Println(v)
}

unbuffered channel

下面这两种声明是一样的

    c1 := make(chan bool, )  // unbuffered channel
c2 := make(chan bool) // unbuffered channel

  unbuffered channel  的接收channel会一直阻塞,直到有值传给channel, 也可以说发送channel会一直阻塞,至到有接收channel

    c1 := make(chan bool, )  // unbuffered channel
c2 := make(chan bool) // unbuffered channel go func() {
c1 <- false
time.Sleep(time.Second * )
c2 <- true
}() fmt.Println(<-c1)
fmt.Println(<-c2)

相关讲解:

https://stackoverflow.com/questions/23233381/whats-the-difference-between-c-makechan-int-and-c-makechan-int-1

https://golang.org/doc/effective_go.html

定义类型和组合类型的区别

  定义类型,也可以说是别名和组合类型的区别

   有一个Test的结构,NewTest是以Test为类型的一个定义,New2Test和New3Test都是组合类型

type Test struct         { N int }
func (m *Test) Name() { fmt.Println("abc")} // NewTest does not inherit any functions of Test
// can access fields
type NewTest Test // New2Test is composite type, it inherit all functions of Test
// can access fields
type New2Test struct {
Test
} // if embedded type is pointer you must initialized it
type New3Test struct {
*Test
}

1.定义类型NewTest 相当于一个新的类型,他不能直接调用Test的方法,但是可以访问Test的字段。如果想调用原类型的方法需要做转换

2.New2Test和New3Test都是组合类型,他俩都可以直接调用Test的方法和访问Test的字段,他俩的不同之处就是一个是值组合一个是指针组合

   3.在实例化New3Test的时候需要手动实例化*Test指针

    n := NewTest{}
n.N =
// n have no method
// n.Name() // error
v := (*Test)(&n)
v.Name() v2 := Test(n)
v2.Name() n2 := New2Test{}
n2.N =
n2.Name() n3 := New3Test{Test: new(Test)}
// access filed N will panic if you do not initialized *Test
n3.N =
n3.Name()

  相关的解答:

https://stackoverflow.com/questions/28800672/how-to-add-new-methods-to-an-existing-type-in-go/28800807#28800807

https://golang.org/ref/spec#Type_declarations

---

golang 常见疑惑总结的更多相关文章

  1. golang 常见变成问题01

    Golang常见编程问题 --语言简单 func CopyFile (dst, src string) (w int64, err error) { srcFile, err := os.Open ( ...

  2. Golang 常见设计模式之单例模式

    之前我们已经看过了 Golang 常见设计模式中的装饰和选项模式,今天要看的是 Golang 设计模式里最简单的单例模式.单例模式的作用是确保无论对象被实例化多少次,全局都只有一个实例存在.根据这一特 ...

  3. Golang 常见设计模式之选项模式

    熟悉 Python 开发的同学都知道,Python 有默认参数的存在,使得我们在实例化一个对象的时候,可以根据需要来选择性的覆盖某些默认参数,以此来决定如何实例化对象.当一个对象有多个默认参数时,这个 ...

  4. Golang常见误区(二)

    35. 关闭 HTTP 的响应体 使用 HTTP 标准库发起请求.获取响应时,即使你不从响应中读取任何数据或响应为空,都需要手动关闭响应体.新手很容易忘记手动关闭,或者写在了错误的位置: // 请求失 ...

  5. Linux网络编程系列-常见疑惑

    1.并发TCP最大连接数 一个TCP连接有一个四元组唯一标识{local_ip, local_port, remote_ip, remote_port} client端建立连接请求时,通常让系统分配一 ...

  6. Golang常见误区(一)

    1.左大括号一般不能单独一行 在其他大多数语言中,{ 的位置你自行决定.Go 比较特别,遵守分号注入规则(automatic semicolon injection):编译器会在每行代码尾部特定分隔符 ...

  7. golang常见错误

    import import unuse package: error : imported and not used: "os" := = c := 1 // error non- ...

  8. Java语法基础常见疑惑解答8,16,17,21图片补充

    8. 16. 17. 21

  9. Java语法基础常见疑惑解答

    1. 类是java的最小单位,java的程序必须在类中才能运行 2. java函数加不加static有何不同 java中声明为static的方法称为静态方法或类方法.静态方法可以直接调用静态方法,访问 ...

随机推荐

  1. C++中const加强

    demo // C语言中的const是一个冒牌货 int main() { // 好像a是一个常量 const int a = 10; int *p = NULL; p = (int *)&a ...

  2. Mysql join语句的优化

    Mysql4.1开始支持SQL的子查询.这个技术可以使用SELECT语句来创建一个单列的查询结果,然后把这个结果作为过滤条件用在另一个查询中.使用子查询可以一次性的完成很多逻辑上需要多个步骤才能完成的 ...

  3. Spring MVC 入门示例讲解 - howtodoinjava

    在本例中,我们将使用Spring MVC框架构建一个入门级web应用程序.Spring MVC 是Spring框架最重要的的模块之一.它以强大的Spring IoC容器为基础,并充分利用容器的特性来简 ...

  4. Chapter 2 User Authentication, Authorization, and Security(9):防止登录名和用户查看元数据

    原文出处:http://blog.csdn.net/dba_huangzj/article/details/39003679,专题目录:http://blog.csdn.net/dba_huangzj ...

  5. 阿里电话面试问题----100万个URL如何找到出现频率最高的前100个?

    内推阿里电话面试中面试官给我出的一个题: 我想的头一个解决方案,就是放到stl 的map里面对出现的频率作为pair的第二个字段进行排序,之后按照排序结果返回: 下面口说无凭,show your co ...

  6. SpringMVC中通过@ResponseBody返回对象,Js中调用@ResponseBody返回值,统计剩余评论字数的js,@RequestParam默认值,@PathVariable的用法

    1.SpringMVC中通过@ResponseBody.@RequestParam默认值,@PathVariable的用法 package com.kuman.cartoon.controller.f ...

  7. leetcode之 Generate Parentheses

    题目:http://oj.leetcode.com/problems/generate-parentheses/ 描述:给定一个非负整数n,生成n对括号的所有合法排列. 解答: 该问题解的个数就是卡特 ...

  8. mysql进阶(二十三)数据库事务四大特性

    数据库事务四大特性       原子性.一致性.分离性.持久性 原子性  事务的原子性指的是,事务中包含的程序作为数据库的逻辑工作单位,它所做的对数据修改操作要么全部执行,要么完全不执行.这种特性称为 ...

  9. Android数据库Realm实践

    Android开发中常用的数据库有5个: 1. OrmLite OrmLite 不是 Android 平台专用的ORM框架,它是Java ORM.支持JDBC连接,Spring以及Android平台. ...

  10. android 开源图表库MPChart最简单使用方法示例教程Demo--折线图 柱状图

    转载请注明本文出处:http://blog.csdn.net/wingichoy/article/details/50428246 MPChart是android上一款强大的图表开源库,他可以轻松的绘 ...