golang 函数默认参数函数中的参数为什么不支持默认值

7223人阅读
golang(18)
go语言函数作为参数传递,目前给我的感觉几乎和C/C++一致。非常的灵活。
import &fmt&
import &time&
func goFunc1(f func()) {
func goFunc2(f func(interface{}), i interface{}) {
func goFunc(f interface{}, args... interface{}) {
if len(args) & 1 {
go f.(func(...interface{}))(args)
} else if len(args) == 1 {
go f.(func(interface{}))(args[0])
go f.(func())()
func f1() {
fmt.Println(&f1 done&)
func f2(i interface{}) {
fmt.Println(&f2 done&, i)
func f3(args... interface{}) {
fmt.Println(&f3 done&, args)
func main() {
goFunc1(f1)
goFunc2(f2, 100)
goFunc(f1)
goFunc(f2, &xxxx&)
goFunc(f3, &hello&, &world&, 1, 3.14)
time.Sleep(5 * time.Second)
f2 done 100
f2 done xxxx
f3 done [[hello world 1 3.14]]
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:678360次
积分:8402
积分:8402
排名:第1868名
原创:207篇
转载:37篇
评论:63条
(1)(2)(3)(4)(3)(13)(8)(1)(3)(1)(4)(1)(2)(1)(15)(6)(3)(2)(4)(2)(8)(14)(3)(7)(1)(3)(6)(3)(7)(3)(6)(1)(7)(6)(11)(9)(10)(9)(18)(8)(21)(4)golang struct结构体方法中的参数需要定义为指针类型
前几日写一个网页的简单计数器问题时发现,计数器居然永远为0,计数器不计数,见鬼了。。。
代码如下:
type Counter struct { &
& & n int &
func (ctr Counter) ServeHTTP(c http.ResponseWriter, req *http.Request) { &
& & fmt.Fprintf(c, &%08x\n&, ctr) &
& & ctr.n++ &
& & fmt.Fprintf(c, &counter = %d\n&, ctr.n) &
func main() { &
& & http.Handle(&/counter&, new(Counter)) &
& & log.Fatal(&ListenAndServe: &, http.ListenAndServe(&:80&, nil)) &
研究一番,发现我们
func (ctr Counter) ServeHTTP(c http.ResponseWriter, req *http.Request) &&
func (ctr* Counter) ServeHTTP(c http.ResponseWriter, req *http.Request) &&
也就是说,对象的实例必须定义为指针的类型,然后才能传递正确的地址,否则ctr参数只是对象的一个副本,
于是修正代码为:
type Counter struct { &
& & n int &
func (ctr *Counter) ServeHTTP(c http.ResponseWriter, req *http.Request) { &
& & fmt.Fprintf(c, &%08x\n&, ctr) &
& & ctr.n++ &
& & fmt.Fprintf(c, &counter = %d\n&, ctr.n) &
func main() { &
& & http.Handle(&/counter&, new(Counter)) &
& & log.Fatal(&ListenAndServe: &, http.ListenAndServe(&:80&, nil)) &
计数器终于计数了。。。
总结:golang隐式传递指针,但是不隐式定义指针,此坑需同学们注意。
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467142',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'Go语言可变参数函数,何时该使用省略号(...)
| Go语言中文网 | Golang中文社区 | Golang中国
<meta name="author" content="polaris ">
Go语言可变参数函数,何时该使用省略号(...)
Go语言可变参数函数,何时该使用省略号(...)
今天的一个例子中发现,对于在调用可变参数函数时,不是总能使用省略号将一个切片展开,有时候编译器可能会报错,为了清除的说明这个问题,我用几个小例子一步一步说明。
1、提出假想的需求
假如想要在一堆数据中找出最小的一个,该怎么做?
如果数据的类型为int,那么我可以这么做:
func MinimumInt(first int, others ...int) int {
min := first
for _, value := range others {
if value & min {
min = value
return min
上述的MinimumInt函数的第二个参数声明为:others …int,表示这是一个可变参数,可以给它传入0个或者任意多个int型参数,在花栗鼠内部,它被表示成一个切片。而声明第一个参数,仅仅是为了让调用者必须传入至少一个参数,如果写成
func MinimumInt(others ...int) int {
则此函数接收一个可变参数,甚至长度可为0(即不传入参数),显然,不传入参数时调用该函数不满足提出的需求。
对于MinimumInt函数的调用,可通过如下的几种方式:
MinimumInt(10, 15, 32, 46, 2, 3)
var sliceInt = []int{10, 15, 32, 46, 2, 3}
MinimumInt(sliceInt[0], sliceInt[1], sliceInt[2], sliceInt[3], sliceInt[4], sliceInt[5])
MinimumInt(sliceInt[0], sliceInt[1:]...)
对于第一种调用方式,直接使用了int类型的字面值常量来作为参数,在MinimumInt函数内部除第一参数外的所有参数被放入到了一个int型切片中进行处理;
第二种调用方式,本质上和第一种相同,只是不再使用字面值常量,而事先构建了一个int型切片,使用该切片的元素依次作为参数;
第三种调用方式,实际上可看做第二种的简化版本,只不过使用了省略号(…)来自动展开切片;
2、完善需求
上面的例子中,我们仅仅做了对int型数据的处理,如果数据是其他类型呢?能否实现一个通用的处理函数,可以处理几乎所有类型的数据?
对于这个问题,在C++中很容易通过泛型来解决,Go中虽不支持这么做,但也还是有解决方法–空接口
func Minimum(first interface{}, rest ...interface{}) interface{} {
min := first
for _, value := range rest {
switch value := value.(type) {
if value & min.(int) {
min = value
case float64:
if value & min.(float64) {
min = value
case string:
if value & min.(string) {
min = value
return min
对于上述函数,将其参数类型声明为空接口interface{},同时返回值也为interface{},这样,该函数就能接收任意类型的数据,并且对于第二个参数来说,参数的数目也是任意的。然后在函数中使用非检查类型断言来分别处理不同类型的数据,这里使用了一个基于类型开关的switch语句。
对于Minimum函数的调用方式,先做一些尝试:
Minimum(10, 15, 32, 46, 2, 3)
var sliceInt = []int{10, 15, 32, 46, 2, 3}
Minimum(sliceInt[0], sliceInt[1], sliceInt[2], sliceInt[3], sliceInt[4], sliceInt[5])
Minimum(sliceInt[0], sliceInt[1:]...)
总体来说,调用方式和MinimumInt函数一致:
第一个直接使用字面值常量;
第二个先构造切片,依次使用每个元素
第三个使用切片,并试图用省略号自动展开切片以使用每个元素
但是,当我们编译时却发现编译器报告了错误:
# command-line-arguments
./test.go:14: cannot use sliceInt[1:] (type []int) as type []interface {} in argument to Minimum
这种错误发生在了第三种调用方式上,而这里就显得有些奇怪了,在MinimumInt函数中使用省略号自动展开一个切片都是正常的啊!
于是我将调用方式改成了如下:
([0], [1:])
编译就通过了,但是这样调用后并不能得到数据中的最小值,原因稍后解释!
然后,本着好奇,我尝试着将MinimumInt函数的调用方式改成了如下:
MinimumInt(sliceInt[0], sliceInt[1:])
再次编译,我得到了如下的错误提示:
# command-line-arguments
./test.go:15: cannot use sliceInt[1:] (type []int) as type int in argument to MinimumInt
由上提示,很容易得出一个结论:MinimumInt函数的第二个参数others在编译器看来仅仅是一个int型变量,尽管在MinimumInt函数内部它是一个int型切片([]int),所以我们传入参数时需要使用省略号来将一个切片展开成一个一个的元素,这样才能做到参数匹配(Go不支持默认的类型转换)
对于interface{}空接口,它可以代指任何类型的数据,比如:
var i int = 10
var sliceInt = []int{10, 15, 32, 46, 2, 3}
var sliceIntz [][]int = [][]int{[]int{1, 2, 3}, []int{4, 5, 6}, []int{7, 8, 9}}
var inter_a interface{} = i
var inter_b interface{} = sliceInt
var inter_c interface{} = sliceIntz
可见interface{}可指代int型数据,又可指代[]int型数据和[][]int型数据。
可能有人会认为,interface{}可用于指代int型数据,那么是不是[]interface{}就是指代[]int型数据的呢?那么做一个测试:
var inter_d []interface{} = sliceInt[:]
而在编译时,编译器报告错误:
# command-line-arguments
./test.go:27: cannot use sliceInt[:] (type []int) as type []interface {} in assignment
既它们类型不兼容,不能直接赋值!不过按照常理来说,好像是可以这么做的?为什么会报错呢?
原因在于,对于var inter_d []interface{}声明,其实我们是在声明一个切片,该切片可保存任意类型的值,可是切片的定义语句却不是这样的,对于一个已经声明的切片类型,我们只能使用如下的形式来定义:
var inter_d []interface{} = []interface{}{sliceIntz[0], sliceIntz[1], sliceIntz[2]}
这样就不会报错了,那么说到了这里,对于Minimum函数的错误也应该有答案了吧?我们将它的调用方式改成如下:
([0], [1], [2], [3])
这样调用也就没有错误了!因为我们用正确的方式构造了一个切片!
对于Minimum函数的调用方式,如果写成如下:
([0], [1:])
虽然编译通过,但是却无法得到正确的最小值,因为我们在传入实参时,传入的是一个切片的引用,而非由一个个值去构建了一个切片!因为此时interface{}本身就指代了[]int类型,虽然reset的类型还是[]interface{},但reset[0]的类型已经发生了变化!
可以来做一个验证,将Minimum函数改成如下形式:
func Minimum(first interface{}, rest ...interface{}) interface{} {
min := first
fmt.Printf(&#34;%T\t%T\n&#34;, rest, rest[0])
for _, value := range rest {
switch value := value.(type) {
if value & min.(int) {
min = value
case float64:
if value & min.(float64) {
min = value
case string:
if value & min.(string) {
min = value
return min
第一种调用方式:
fmt.Println(Minimum(sliceInt[0], sliceInt[1], sliceInt[2], sliceInt[3], sliceInt[4], sliceInt[5]))
第二种调用方式:
fmt.Println(Minimum(sliceInt[0], sliceInt[1:]))
我不知道这种解释是否合理,语言表述的可能不是特别明确,无奈思考再三,觉得只有这种解释稍微合理一些!
版权声明:本文为博主原创文章,未经博主允许不得转载。
支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
支持 @ 本站用户;支持表情(输入 : 提示),见
记住登录状态
还不是会员函数在go中的两种用法——作为参数和返回值 - Golang中国
22:25 发布 2972 次点击
对于之前写过java等静态类型的语言,回调和闭包可能有点陌生,毕竟这些功能是要在发布java8和java9时才完全加入的功能。
就今天学的函数在go中的两种用法,举两个例子简单说明一下。
一:函数作为参数传递
package main
import "fmt"
func main() {
m := []int{1,2,3,4,5}
f := func(i int) int {
return i * i
fmt.Println("%v", (Map(f, m)))
func Map(f func(int) int, l []int) []int {
j := make([]int, len(l))
for k, v := range l {
j[k] = f(v)
二:函数做为返回值返回
package main
import "fmt"
func main() {
p := plusTwo(5)
fmt.Println("%v",
func plusTwo(y int) func(int) int {
return func(x int) int {return x + y}
这两个例子是学习go语言电子书中的练习,很好的应用了函数的回调和闭包。
闭包在实际应用中都用在什么地方?看了维基百科中的解释,闭包有3个用途:
1、因为闭包只有在被调用时才执行操作,所以它可以被用来定义控制结构。
2、多个函数可以使用一个相同的环境,这使得它们可以通过改变那个环境相互交流。
3、闭包可以用来实现对象系统。
只能理解第2个用途,其他用途理解不了。
闭包可以封装一些简单功能只为当前函数使用,不需要单独写一个函数进行调用。不知道go的垃圾回收机制是怎么样的闭包使用外部函数的变量,
如果存在循环引用会不是得到回收?我接触闭包也不是很多,理解的也不是透彻,以后理解的多了再补充。
后方可回复, 如果你还没有账号你可以
一个帐号。新手园地& & & 硬件问题Linux系统管理Linux网络问题Linux环境编程Linux桌面系统国产LinuxBSD& & & BSD文档中心AIX& & & 新手入门& & & AIX文档中心& & & 资源下载& & & Power高级应用& & & IBM存储AS400Solaris& & & Solaris文档中心HP-UX& & & HP文档中心SCO UNIX& & & SCO文档中心互操作专区IRIXTru64 UNIXMac OS X门户网站运维集群和高可用服务器应用监控和防护虚拟化技术架构设计行业应用和管理服务器及硬件技术& & & 服务器资源下载云计算& & & 云计算文档中心& & & 云计算业界& & & 云计算资源下载存储备份& & & 存储文档中心& & & 存储业界& & & 存储资源下载& & & Symantec技术交流区安全技术网络技术& & & 网络技术文档中心C/C++& & & GUI编程& & & Functional编程内核源码& & & 内核问题移动开发& & & 移动开发技术资料ShellPerlJava& & & Java文档中心PHP& & & php文档中心Python& & & Python文档中心RubyCPU与编译器嵌入式开发驱动开发Web开发VoIP开发技术MySQL& & & MySQL文档中心SybaseOraclePostgreSQLDB2Informix数据仓库与数据挖掘NoSQL技术IT业界新闻与评论IT职业生涯& & & 猎头招聘IT图书与评论& & & CU技术图书大系& & & Linux书友会二手交易下载共享Linux文档专区IT培训与认证& & & 培训交流& & & 认证培训清茶斋投资理财运动地带快乐数码摄影& & & 摄影器材& & & 摄影比赛专区IT爱车族旅游天下站务交流版主会议室博客SNS站务交流区CU活动专区& & & Power活动专区& & & 拍卖交流区频道交流区
白手起家, 积分 15, 距离下一级还需 185 积分
论坛徽章:0
本帖最后由 yxtiger 于
17:46 编辑
搜了一下文档,发现没有static关键字
那么函数中的静态变量该怎么实现呢?难道用全局变量?
问题追加:golang是否有函数调用默认值的用法呢?
&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp
白手起家, 积分 137, 距离下一级还需 63 积分
论坛徽章:0
不妨找本资料看看。学一门新语言别把旧语言的东西一个、一个往上套,不然会觉得这也没有,那也没有。而实际这些东西都是有的,或者仅仅是换了一种更优化的表达方式、实现手法。
白手起家, 积分 15, 距离下一级还需 185 积分
论坛徽章:0
楼上的,你倒是找本资料出来试试!你怎么知道我没搜阅大量资料?
白手起家, 积分 15, 距离下一级还需 185 积分
论坛徽章:0
没找到golang关于静态变量的资料,目前只能用全局变量的办法对付一下。
另外,也没有找到golang调用函数默认值的用法。
如果有朋友知道上面两个特性,烦请回帖说一下。谢谢!
白手起家, 积分 35, 距离下一级还需 165 积分
论坛徽章:0
貌似确实没有,转换思路吧,嘿嘿
论坛徽章:44
自信点,没有就是没有呗。不过 go 有 closure 能做出静态变量的效果
稍有积蓄, 积分 312, 距离下一级还需 188 积分
论坛徽章:0
函数参数默认值不是个好东西。在 go 官网的 faq 里有说明为什么不支持。
论坛徽章:1
提示: 作者被禁止或删除 内容自动屏蔽
北京皓辰网域网络信息技术有限公司. 版权所有 京ICP证:060528号 北京市公安局海淀分局网监中心备案编号:
广播电视节目制作经营许可证(京) 字第1234号
中国互联网协会会员&&联系我们:
感谢所有关心和支持过ChinaUnix的朋友们
转载本站内容请注明原作者名及出处

我要回帖

更多关于 golang 函数默认参数 的文章

 

随机推荐