Go语言入门【java->go】

简介: Go语言入门【java->go】

为什么是Go语言

  • 类C的语法,这意味着Java、C#、JavaScript程序员能很快的上手
  • 有自己的垃圾回收机制
  • 跨平台、编译即可执行无需安装依赖环境
  • 支持反射

Go语言简介

Go 语言(或 Golang)起源于 2007 年,并在 2009 年正式对外发布。Go 是非常年轻的一门语言,它的主要目标是“兼具Python等动态语言的开发速度和 C/C++ 等编译型语言的性能与安全性”。

数据类型

数据类型 说明
bool 布尔
string 字符串
int uint8,uint16,uint32,uint64,int8,int16,int32,int64
float float32,float64
byte byte

参考:www.runoob.com/go/go-data-…

基本语法

HelloWorld

在线运行示例:play.golang.org/p/-4RylAqUV…

package main
 
import "fmt"
 
var name string
 
func init() {
  name = "world"
}
 
func main() {
  fmt.Println("hello " + name)
}
复制代码

我们来执行一下:

$ go run main.go # main.go 为刚刚创建的那个文件的名称
$ hello world
复制代码

变量

变量声明

在线运行示例:play.golang.org/p/zPqCkRZgr…

package main
 
import (
  "fmt"
)
 
func main() {
  var name string   // 声明
  name = "da'mao'mao" // 赋值
  fmt.Println(name)
 
  var age int = 18 // 声明并赋值
  fmt.Println(age)
}
复制代码

类型推断

在线运行示例:play.golang.org/p/0My8veBvt…

package main
 
import (
  "fmt"
)
 
func main() {
  name := "damaomao"
  fmt.Println(name)
 
  age := 18
  fmt.Println(age)
}
复制代码

函数

  • 函数可以有多个返回值
  • 隐式的指定函数是private还是public,函数首字母大写的为public、小写的为private
  • 没有类似Java中的try cachethrow,Go语言是通过将error作为返回值来处理异常。
  • 不支持重载

下面我们通过一个示例来了解一下,在线运行示例:play.golang.org/p/PYy3ueuPF…

package main
 
import (
  "errors"
  "fmt"
  "strconv"
)
 
func main() {
  log1()
 
  log2("hello world")
 
  ret1 := add1(1, 1)
  fmt.Println("add1 result:" + strconv.Itoa(ret1))
 
  ret2, err := Add2(0, 1)
  if err == nil {
    fmt.Println("Add2 result:" + strconv.Itoa(ret2))
  } else {
    fmt.Println("Add2 error", err)
  }
}
 
// 私有、无入参、无返回值
func log1() {
  fmt.Println("execute func log1")
}
 
// 私有、入参、无返回值
func log2(msg string) {
  fmt.Println("execute func log2:" + msg)
}
 
// 私有、两个入参、一个返回值
func add1(count1, count2 int) int {
  total := count1 + count2
  fmt.Println("execute func add3, result=" + strconv.Itoa(total))
  return total
}
 
// Public、两个入参、多个返回值
func Add2(count1, count2 int) (int, error) {
  if count1 < 1 || count2 < 1 {
    return 0, errors.New("数量不能小于1")
  }
  total := count1 + count2
  return total, nil
}
复制代码

该示例输出结果为:

execute func log1
execute func log2:hello world
execute func add3, result=2
add1 result:2
Add2 error 数量不能小于1
复制代码

但函数有多个返回值的时候,有时你只关注其中一个返回值,这种情况下你可以将其他的返回值赋值给空白符:_,如下:

_, err := Add2(1, 2)
if err != nil {
  fmt.Println(err)
} 
复制代码

空白符特殊在于实际上返回值并没有赋值,所以你可以随意将不同类型的值赋值给他,而不会由于类型不同而报错。

结构体

Go语言不是像Java那样的面向对象的语言,他没有对象和继承的概念。也没有class的概念。在Go语言中有个概念叫做结构体(struct),结构体和Java中的class比较类似。下面我们定义一个结构体:

type User struct {
  Name   string
  Gender string
  Age    int
}
复制代码

上面我们定义了一个结构体User,并为该结构体分别设置了三个公有属性:Name/Gender/Age,下面我们来创建一个User对象。

user := User{
  Name:   "hahaha",
  Gender: "男",
  Age:    18, // 值得一提的是,最后的逗号是必须的,否则编译器会报错,这就是go的设计哲学之一,要求强一致性。
}
复制代码

结构体的属性可以在结构体内直接声明,那么如何为结构体声明函数(即Java中的方法)呢,我们来看下下面的示例:在线运行示例:play.golang.org/p/01_cTu0Rz…

package main
 
import "fmt"
 
type User struct {
  Name   string
  Gender string
  Age    int
}
 
// 定义User的成员方法
func (u *User) addAge() {
  u.Age = u.Age + 1
}
 
func main() {
  user := User{
    Name:   "哈", // 名称
    Gender: "男", // 性别
    Age:    18,  // 值得一提的是,最后的逗号是必须的,否则编译器会报错,这就是go的设计哲学之一,要求强一致性。
  }
  user.addAge()
  fmt.Println(user.Age)
}
复制代码

指针类型和值类型

Java中值类型和引用类型都是定死的,int、double、float、long、byte、short、char、boolean为值类型,其他的都是引用类型,而Go语言中却不是这样。

在Go语言中:

  • &表示取地址,例如你有一个变量a那么&a就是变量a在内存中的地址,对于Golang指针也是有类型的,比如a是一个string那么&a是一个string的指针类型,在Go里面叫&string。
  • *表示取值,接上面的例子,假设你定义b := &a 如果你打印b,那么输出的是&a的内存地址,如果要取值,那么需要使用:*b

下面我们来看下例子,在线运行:play.golang.org/p/jxAKyVMjn…

package main
 
import (
  "fmt"
)
 
func main() {
  a := "123"
  b := &a
 
  fmt.Println(a)
  fmt.Println(b)
  fmt.Println(*b)
}
 
输出结果为:
123
0x40c128
123
复制代码

并发编程

Go语言的并发是基于 goroutine 的,goroutine 类似于线程,但并非线程。可以将 goroutine 理解为一种虚拟线程。Go语言运行时会参与调度 goroutine,并将 goroutine 合理地分配到每个 CPU 中,最大限度地使用CPU性能。

Go 程序从 main 包的 main() 函数开始,在程序启动时,Go 程序就会为 main() 函数创建一个默认的 goroutine。

下面我们来看一个例子(在线演示:play.golang.org/p/U9U-qjuY0…

package main
 
import (
  "fmt"
  "time"
)
 
func main() {
  // 创建一个goroutine
  go runing()
  // 创建一个匿名的goroutine
  go func() {
    fmt.Println("喜特:" + time.Now().String())
  }()
 
  // 这里sleep一下是因为main方法如果执行完了,main该程序创建的所有goroutine都会退出
  time.Sleep(5 * time.Second)
}
 
func runing() {
  fmt.Println("法克:" + time.Now().String())
  time.Sleep(3 * time.Second)
}
 
输出:
法克:2009-11-10 23:00:00 +0000 UTC m=+0.000000001
喜特:2009-11-10 23:00:00 +0000 UTC m=+0.000000001
复制代码

执行结果说明fuck函数中的sleep三秒并没有影响喜特的输出。

如果说 goroutine 是Go语言程序的并发体的话,那么 channel 就是它们之间的通信机制。一个 channel 是一个通信机制,它可以让一个 goroutine 通过它给另一个 goroutine 发送值信息。每个 channel 都有一个特殊的类型,也就是 channel 可发送数据的类型。一个可以发送 int 类型数据的 channel 一般写为 chan int。

下面我们利用goroutine+channel来实现一个生产消费者模型,示例代码如下:(在线执行:play.golang.org/p/lqUBugLdU…

package main
 
import (
  "fmt"
  "time"
)
 
func main() {
  // 创建一个通道
  channel := make(chan int64)
 
  // 异步去生产
  go producer(channel)
 
  // 数据消费
  consumer(channel)
}
 
// 生产者
func producer(channel chan<- int64) {
  for {
    // 将数据写入通道
    channel <- time.Now().Unix()
    // 睡1秒钟
    time.Sleep(time.Second)
  }
}
 
// 消费者
func consumer(channel <-chan int64) {
  for {
    timestamp := <-channel
    fmt.Println(timestamp)
  }
}
 
输出为如下:(每秒钟打印一次)
1257894000
1257894001
1257894002
1257894003
复制代码

Java程序员觉得不好用的地方

  • 异常处理
  • 没有泛型
  • 不支持多态、重载
  • 不支持注解(但是他的struct中的属性支持tag
相关文章
|
2月前
|
监控 Java API
如何使用Java语言快速开发一套智慧工地系统
使用Java开发智慧工地系统,采用Spring Cloud微服务架构和前后端分离设计,结合MySQL、MongoDB数据库及RESTful API,集成人脸识别、视频监控、设备与环境监测等功能模块,运用Spark/Flink处理大数据,ECharts/AntV G2实现数据可视化,确保系统安全与性能,采用敏捷开发模式,提供详尽文档与用户培训,支持云部署与容器化管理,快速构建高效、灵活的智慧工地解决方案。
|
1天前
|
自然语言处理 Java
Java中的字符集编码入门-增补字符(转载)
本文探讨Java对Unicode的支持及其发展历程。文章详细解析了Unicode字符集的结构,包括基本多语言面(BMP)和增补字符的表示方法,以及UTF-16编码中surrogate pair的使用。同时介绍了代码点和代码单元的概念,并解释了UTF-8的编码规则及其兼容性。
72 60
|
1月前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
56 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
28天前
|
监控 架构师 Java
Java虚拟机调优的艺术:从入门到精通####
本文作为一篇深入浅出的技术指南,旨在为Java开发者揭示JVM调优的神秘面纱,通过剖析其背后的原理、分享实战经验与最佳实践,引领读者踏上从调优新手到高手的进阶之路。不同于传统的摘要概述,本文将以一场虚拟的对话形式,模拟一位经验丰富的架构师向初学者传授JVM调优的心法,激发学习兴趣,同时概括性地介绍文章将探讨的核心议题——性能监控、垃圾回收优化、内存管理及常见问题解决策略。 ####
|
2月前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
2月前
|
SQL 安全 Java
安全问题已经成为软件开发中不可忽视的重要议题。对于使用Java语言开发的应用程序来说,安全性更是至关重要
在当今网络环境下,Java应用的安全性至关重要。本文深入探讨了Java安全编程的最佳实践,包括代码审查、输入验证、输出编码、访问控制和加密技术等,帮助开发者构建安全可靠的应用。通过掌握相关技术和工具,开发者可以有效防范安全威胁,确保应用的安全性。
57 4
|
2月前
|
存储 设计模式 安全
Go语言中的并发编程:从入门到精通###
本文深入探讨了Go语言中并发编程的核心概念与实践技巧,旨在帮助读者从理论到实战全面掌握Go的并发机制。不同于传统的技术文章摘要,本部分将通过一系列生动的案例和代码示例,直观展示Go语言如何优雅地处理并发任务,提升程序性能与响应速度。无论你是Go语言初学者还是有一定经验的开发者,都能在本文中找到实用的知识与灵感。 ###
|
2月前
|
Java 大数据 API
14天Java基础学习——第1天:Java入门和环境搭建
本文介绍了Java的基础知识,包括Java的简介、历史和应用领域。详细讲解了如何安装JDK并配置环境变量,以及如何使用IntelliJ IDEA创建和运行Java项目。通过示例代码“HelloWorld.java”,展示了从编写到运行的全过程。适合初学者快速入门Java编程。
|
2月前
|
Serverless Go
Go语言中的并发编程:从入门到精通
本文将深入探讨Go语言中并发编程的核心概念和实践,包括goroutine、channel以及sync包等。通过实例演示如何利用这些工具实现高效的并发处理,同时避免常见的陷阱和错误。
|
2月前
|
Java 程序员 数据库连接
Java中的异常处理:从入门到精通
在Java编程的海洋中,异常处理是一艘不可或缺的救生艇。它不仅保护你的代码免受错误数据的侵袭,还能确保用户体验的平稳航行。本文将带你领略异常处理的风浪,让你学会如何在Java中捕捉、处理和预防异常,从而成为一名真正的Java航海家。