来自朝鲜的问候

今日在看这本书的数据统计时,发现了居然有一个来自朝鲜的UV,一时激动特意拍照留念

来自朝鲜的问候 - 图1

为了纪念这个特殊的时刻,本节特意取名<来自朝鲜的问候>。也不知道是朝鲜哪位兄台访问此本书,从PV上面来看只点击了10次,估计八成是看不懂中文,随便点了点就走了。 但对于我来说,这个UV却显得弥足珍贵。也不知道这位用户是"革命武装力量的最高领导人"的哪位亲戚好友,如果能看到这篇文章,可否引荐一下?(이 사람이'혁명 무장 역량의 최고 지도자'라고 할 수 있는 어느 친척인 데,이 글을 볼 수 있 다면, 추천을 받을 수 있 을지도 모 른다.)

话说回来,技术无国界。我们一衣带水的邻居想学点技术怎么了?想看点入门教程又怎么了?你们那里招聘Golang工程师不?我可以在家办公,远程帮助你们解决问题,冲着这份伟大的国际友谊,我都不好意思提钱的事情,您看着给!(당신들은 Golang 엔지니어를 채용 합니까?나는 집에서 일 할 수 있고, 장거리도 너희들에게 문제를 해결하고,이 위대 한 국제적인 우정을 가지고 있 는데,나는 돈을 말 할 수 없는 일을, 당신이 바라 보고 있다!)

谢谢有道词典,把我的意思翻译的八九不离十,除了有道,暂时没有好用的翻译软件了,只能忍之再忍。如果你也想参与到这场伟大的技术革命浪潮中,留个联系方式给我。等哪天金正恩同志召唤我了,我再组团召唤你们。为了革命!我们时刻在准备着(혁명을 위하여!우리는 항상 준비하고 있다.)。朝鲜朋友看到这里就可以了,下面我要写golang了。

我的风格一向是想到哪里,就写到哪里。前几天在写程序的时候,有一段死循环了。仔细看了看,是递归算法的退出条件有问题了。这节就先说递归吧。

递归

简单来说,递归就是重复调用同一个函数过程来解析相同的问题。转换成人话,就是自己调自己。伪代码如下:

  1. func recursion() {
  2. recursion()
  3. }
  4. func main() {
  5. recursion()
  6. }

大多数程序语言都支持这种调用方式,使用递归时,一定要注意退出条件,否则就会跟我一样,出现死循环!因为递归属于算法中的一种,按道理来说应该是放在算法书中讲解最好。所以就用一个例子来提醒所有使用递归的人,一定要注意退出条件!

  1. package main
  2. import "fmt"
  3. func fibonaci(i int) (ret int) {
  4. if i == 0 {
  5. return 0
  6. }
  7. if i == 1 {
  8. return 1
  9. }
  10. return fibonaci(i-1) + fibonaci(i-2)
  11. }
  12. func main() {
  13. var i int
  14. for i = 0; i < 10; i++ {
  15. fmt.Printf("%d ", fibonaci(i))
  16. }
  17. }

上面两个if就是用来判断退出条件的。如果退出条件,写得好,递归就不会出现问题。在我的死循环案例中,是在if环节,用来判断两个变量类型是否一致时出现了问题,导致永远是false,因此死了循环%>_<%。于是乎,趁热打铁,下面说一下Golang如何进行类型强转。

类型转换和类型断言

Golang中涉及到类型的操作有两种,一种是类型转换,一种是类型断言。

先说类型转换,Golang的类型分为两种,一种是静态类型,一种是底层类型。比如:

  1. type myString string

通过type关键字声明了自己的类型myString。myString则是静态类型,而string则是底层类型。如果底层类型相同,则两种类型可以转换成功,反之则失败。如果不知道底层类型,则可以调用reflect的Kind方法来获取,如下:

  1. fmt.Printf("%v",reflect.Kind(count))

int32

在Golang当中还有接口类型interface{}。很多时候,会将普通类型转换成interface{},这个过程是隐式推导,用户无感知。但如果反向,将interface{}向普通类型进行转换,则需要进行显示推导。这个时候就需要进行类型断言.

断言方式分两种:

第一种,Comma-ok:

  1. value, ok := element.(T)
  2. 比如:
  3. var a interface{}
  4. value, ok := a.(string)
  5. if !ok {
  6. fmt.Println("It's not ok for type string")
  7. return
  8. }

如果OK == true,表示a是string类型。反正,则表示不是string类型。

第二种,switch判断:

  1. var t interface{}
  2. t = functionOfSomeType()
  3. switch t := t.(type) {
  4. case bool:
  5. fmt.Printf("boolean %t\n", t) // t has type bool
  6. case int:
  7. fmt.Printf("integer %d\n", t) // t has type int
  8. case *bool:
  9. fmt.Printf("pointer to boolean %t\n", *t) // t has type *bool
  10. case *int:
  11. fmt.Printf("pointer to integer %d\n", *t) // t has type *int
  12. default:
  13. fmt.Printf("unexpected type %T", t) // %T prints whatever type t has
  14. }

优点就是可以节省代码,本质和Comma-OK一样。

综合起来,golang类型转换就是三条规则:

  • 普通类型向interface{}转换是隐式。
  • interface{}向普通类型转换必须显示
  • 强制转换时,最好使用类型断言,防止panic。