Язык GO в PHPER

Go PHP

Статья впервые опубликована в паблике [Programmer Reading], прошу обратить внимание.

Язык Go — это язык C 21 века. Он имеет производительность, близкую к C/C++ и другим компилируемым языкам, и его так же легко освоить, как языки сценариев (PHP, Javascript, Python). сильная команда разработчиков и активное сообщество.

Особенности языка Go

  • Простой синтаксис
  • Уровень языка поддерживает параллельное программирование
  • Кроссплатформенная компиляция
  • Механизм восстановления мусора в себе

Операторы языка Go не требуют точки с запятой

package main 

import "fmt"

func main(){
    
    s := "hello world"
    
    fmt.Println(s)
}

тип данных

Go — язык со строгой типизацией, и при объявлении переменной нужно указывать, к какому типу относится эта переменная.

var i int = 10

b := 10//错误

func Test(){
    
    s := 10
    
    s := "test"//错误
}

PHP — слаботипизированный язык программирования, при объявлении переменной нельзя указывать тип переменной, который выводится самим языком, но впоследствии переменной могут быть присвоены значения других типов.

$a = 10;

$a = "test";

для, если и переключатель

forЗаявление,ifзаявление иswitchУсловное тело оператора не нуждается в круглых скобках.()

for i := 0; i < 10; i++ {

}

i := 10

if i == 10 {

}
x := 10

switch x{
    
}

switch

  • оператор переключения в PHP
$a = 10;
switch ($a) {
    case 10:
        echo "111";
        break;
    case 20:
        echo "222";
        break;
}

Оператор переключения Go

func main() {
   var level string = "B"
   var score int = 90

   switch score {
      case 90: level = "A"
      case 80: level = "B"
      case 50,60,70 : level = "C"
      default: level = "D"  
   }

   switch {
      case level == "A" :
         fmt.Printf("优秀!\n" )    
      case level == "B", level == "C" :
         fmt.Printf("良好\n" )      
      case level == "D" :
         fmt.Printf("及格\n" )      
      case level == "F":
         fmt.Printf("不及格\n" )
      default:
         fmt.Printf("差\n" );
   }
   fmt.Printf("你的成绩为: %s\n", level );      
}
  • ключевое слово
package main

import "fmt"

func main() {
    switch {
    case false:
            fmt.Println("1、case 条件语句为 false")
            fallthrough
    case true:
            fmt.Println("2、case 条件语句为 true")
            fallthrough
    case false:
            fmt.Println("3、case 条件语句为 false")
            fallthrough
    case true:
            fmt.Println("4、case 条件语句为 true")
    case false:
            fmt.Println("5、case 条件语句为 false")
            fallthrough
    default:
            fmt.Println("6、默认 case")
    }
}

цикл

В отличие от других программ, язык Go поддерживаетwhileилиdo...whileзаявление, не похожее на PHPforeach, цикл Go имеет толькоforутверждение

  • нормальный цикл
for i := 0; i < 10; i++ {

}
  • Обход массива, карты или среза
for k,v := range arr {
    
    
}

переменная видимость

В PHP, если вы не используете классы, видимость переменных отсутствует, и все глобальные переменные объявлены:

a.php

$a = 10;

b.php

include_once("a.php");

echo $a;//输出10

Если вы используете класс, члены класса, из-за общедоступных, защищенных, частных трех, чтобы различать видимость членов.

class A{
    
    public $a;
    
    private $b;
    
    protected $c;
    
}

class B extends A{
    
    
}

Язык Go организует код в пакеты, а видимость переменных очень проста.ИнициалыВиден ли пакет в верхнем регистре и все ли видны

a.go

package my


var Username string = "test"

var age int = 20

const Test = "test"

const t = 123

b.go

package my


func GetUsername() string {
    return Username
}

func GetAge()int{
    return getAge()
}

func getAge()int{
    return a
}

main.go

package main

import "my"
import "fmt"

func main(){
    fmt.Println(my.Username)
    fmt.Println(my.GetUsername())
    fmt.Println(my.GetAge())
    fmt.Println(my.Test)
    fmt.Println(my.age)//错误
    fmt.Println(my.getAge())//错误
    fmt.Println(my.t)//错误
    
}

Нужно ли его компилировать

Статически скомпилированный язык Go, динамический язык сценариев PHP

Поскольку языки сценариев должны интерпретироваться и выполняться интерпретатором, производительность выполнения хуже, чем у скомпилированных языков.

возвращаемое значение функции

Язык PHP, как и большинство языков программирования данных, поддерживает только одно возвращаемое значение для функции или метода, в то время как функция в языке Go напрямую возвращает несколько значений.


func GetFile(path string)(file *os.File,err error){
    
    f,err := os.Open(path)
    
    return f,err
}

пустой идентификатор

Поскольку переменная объявлена ​​и не используется, она не скомпилируется, потому что, когда мы получаем несколько значений от функции, но она нам не понадобится в дальнейшем, мы можем использовать пустой флаг.

func GetFile(path string) *os.File{
    
    file,_ := os.Open(path)
    
    return file
}

Символ двойной кавычки

Строковый тип языка Go не поддерживает одинарные кавычки, тогда как в PHP можно использовать как одинарные, так и двойные кавычки, например:

  • PHP-строка
$a = '';
$b = ""
  • Перейти строки
var s string = "" //必须使用双引号

Объединение с Докером

Программа Go в конечном итоге упакована в виде двоичного файла, который обычно имеет небольшой размер, не более десятков M, и мы можем напрямую упаковать этот двоичный файл в образ Docker.

Однако работа PHP-проектов неотделима от вендора, файла, в котором хранятся все сторонние библиотеки.Этот файл может быть очень большим, и может иметь сотни М. Поэтому, используя docker для упаковки PHP-проектов, образ станет очень большой.

Формат даты замечательная работа

  • Форматирование времени и даты PHP
$t = time();

//Y:年份,m:月份,d:日期,H:时,i:分钟,s:秒
echo date("Y-m-d H:i:s",$t);

  • Форматирование времени и даты на языке Go
//2006:年份,01:月份,02:日期,15/03:时,04:分钟,05:秒
fmt.Println(time.Now().Format("2006-01-02 15:04:05"))

fmt.Println(time.Now().Format("Jan"))//月份
fmt.Println(time.Now().Format("January"))//月份

fmt.Println(time.Now().Format("Monday"))//星期
fmt.Println(time.Now().Format("Mon"))//星期

механизм отлова исключений

PHP, как и другие языки программирования, поддерживает операторы try...catch для перехвата исключений в программах, таких как:

try{
    主要逻辑代码
}catch(Exception $ex){
    异常处理
}

В языке Go нет инструкции try...catch.Предложение по разработке языка Go заключается в том, что программист должен возвращать тип ошибки при разработке.

func main() {
	dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})

	if err != nil {
		log.Fatal("数据库连接错误")
	}

	//主要逻辑代码
}

Если абсолютно необходимо сгенерировать исключение и предотвратить дальнейшее выполнение программы, вы можете использовать функцию panic(), а затем перехватить ее с помощью восстановления.

func Parse(input string) (s *Syntax, err error) {
    defer func() {
        if p := recover(); p != nil {
            err = fmt.Errorf("internal error: %v", p)
        }
    }()
    // ...parser...
    panic("报错啦")
}

defer

Оригинал на языке Go, используемый для последующих операций, таких как освобождение ресурсов после завершения выполнения функции.

func main() {
	f := GetFile("./1.txt")

	defer f.Close()

	f.Write([]byte("test"))
}

func GetFile(path string) *os.File {

	file, _ := os.Open(path)

	return file
}

параллелизм

Go поддерживает параллелизм на уровне языка, используяgoКлючевое слово может просто и напрямую создать горутину, то есть сопрограмму, которую можно понимать как легковесный поток.

func main(){
    go func(){
        fmt.Println("hello world")
    }()
}

  • Coroutine: размер в начале всего 2 КБ и может динамически регулироваться, а максимальный размер может достигать 1 ГБ.

  • Тема: исправлена ​​на 2M.

Поэтому язык Go создает тысячи сопрограмм на одной машине для поддержки высокой степени параллелизма.

Есть два способа взаимодействия сопрограмм, общая память и канал.

объектно-ориентированный

Язык Go не является традиционным объектно-ориентированным языком программирования, не поддерживает классы или объекты, но может имитировать класс через структуру.

type Person struct {
	name string //小写:不可导出
	Age  int    //大写,可导出
}

В отличие от классов, структуры не поддерживают наследование.В отличие от наследования, разработчикам Go рекомендуется использовать композицию структур.

type Student struct{
    
    p Person
    
    number string
}
func main() {

	s := Student{
		p: Person{
			name: "test",
			Age:  10,
		},
		number: "123333",
	}

	fmt.Println(s.number)
	fmt.Println(s.p.name)
}

Анонимное встраивание

type Student struct {
	Person
	number string
}

func main() {

	s := Student{
		Person: Person{
			name: "test",
			Age:  10,
		},
		number: "123333",
	}

	fmt.Println(s.number)
	fmt.Println(s.name)
}

Структуры также могут определять свои собственные методы, такие как классы.


func (s *Student) Say(){
    fmt.Println("My name is:"+s.name)
}

func (s *Student) getName() string{
    return s.name
}

интерфейс

Как и PHP, Go также поддерживает интерфейсы, но разница в том, что в языке Go нет необходимости явно реализовывать интерфейс.

  • PHP реализует интерфейс
interface PosterInterface
{
    public function getData();
}

class ActivityPosterData implements PosterInterface
{
    public function getData(){
        //实现接口
    }
}
  • Go реализует интерфейс

type Reader interface{
    Read(p []byte) (n int, err error)
}


type File struct{
    
}

func (f *File) Read(p []byte) (n int, err error){
    return 10,nil
}

func main() {
	var r Reader
	r = &File{}
	n, err := r.Read([]byte("test"))
	if err != nil {
		panic(err)
	}
	fmt.Println(n)//输出:10
}

пользовательский тип

Go поддерживает определение новых типов поверх существующих типов.

package main

import (
	"fmt"
)

type cm int

func (c cm) Format() string {
	return fmt.Sprintf("%d厘米", c)
}

func (c cm) Read(p []byte) (n int, err error){
    return 20,nil
}

func main() {
	var r Reader

	var i cm = 10
	fmt.Println(i.Format()) //输出:10厘米
	
	r = i
	m, err := r.Read([]byte("cm"))

	if err != nil {
		panic(err)
	}
	fmt.Println(m) //输出:20
}

управление проектом

В PHP мы используем композитор для управления зависимостями проекта, композитор и развитие сообщества, PHP не является официальным, но с самого начала рождения языка Go предоставляет очень надежный инструмент управления проектами.

набор инструментов

$ go build . //编译

$ go run main.go //直接运行

$ go get github.com/spf13/viper //获取第三方包

$ go fmt //格式化

$ go test //单元测试或性能测试

$ go env //打印Go的环境变量

Go Module

//初始化
go mod init jinhongtl/lottery

//整理模块
go mod tidy

//下载依赖包
go mod download

стиль

  • проблема с брекетами

Функции, методы, if, switch, for, в любом месте, где в языке Go используется скобка, фигурные скобки не могут быть в одной строке

//正确
func a(){
    
}

//错误,无法通过编译
func b()
{
    
}

//正确
for i:= 0;i< 10;i++{
    
}
  • проблема с именами
  1. Именование переменных использует имя Luofeng.
Username
username
  1. Рекомендуется использовать строчные буквы для имен пакетов и иметь то же имя, что и каталог.

Разница между веб-разработкой

Рамка

PHP имеет большой и всеобъемлющий фреймворк, такой как Yii, Laravel, эти фреймворки помогли нам разработать множество функций, которые можно использовать напрямую, например, сравнение печати журналов, операции ORM базы данных, очереди, чтение Redis и другие функции.

В языке Go, хотя и есть аналогичные фреймворки для веб-разработки, он чаще используется для настройки разработки в соответствии с вашими потребностями.Например, я просто разрабатываю веб-приложение и читаю базу данных, поэтому мне нужно только обратиться к соответствующую стороннюю библиотеку.

имя библиотеки эффект
github.com/spf13/viper чтение конфигурации
github.com/spf13/cobra структура командной строки
github.com/spf13/pflag аргументы командной строки
github.com/gin-gonic/gin веб-фреймворк
github.com/go-playground/validator Проверка достоверности данных
gorm.io/gorm ORM базы данных
github.com/robfig/cron задача на время
github.com/sirupsen/logrus бревно
go.uber.org/zap бревно
github.com/gorilla/websocket websocket
github.com/go-redis/redis Redis

Способ

Язык Go может напрямую создавать веб-сервер и получать HTTP-запросы всего несколькими строками кода, например:

package main

import "net/http"

func main() {

	http.HandleFunc("/test", func(rw http.ResponseWriter, r *http.Request) {
		rw.Write([]byte("test"))
	})
	http.ListenAndServe(":8088", nil)
}

Если PHP не настроен с nginx или apache, он не может предоставлять только HTTP-сервисы.PHP работает следующим образом:

Рекомендуемый каталог

Если мы используем Go для разработки наших собственных приложений, мы рекомендуем следующую структуру каталогов, которая больше используется сообществом.На основе этой структуры мы можем ссылаться на сторонние библиотеки, которые нам нужны для настройки наших собственных проектов.

├── README.md
├── api
├── assets
├── build
├── cmd
│   ├── apiserver
│   │   └── main.go
│   └── apiauth
│       └── main.go
├── configs
├── deployments
├── docs
├── examples
├── githooks
├── init
├── internal
│   ├── guess
│   ├── lottery
│   └── pkg
├── pkg
├── scripts
├── test
├── third_party
├── tools
├── vendor
├── web
└── website

резюме

По сравнению с PHP, программы, разработанные на языке Go, имеют более высокую производительность и могут поддерживать большое количество параллельных вычислений.Код языка Go также имеет единый стиль.Благодаря полной цепочке инструментов управление проектами упрощается.В то же время язык Go community имеет большое количество одиночных функций, но очень мощная третья сторона позволяет нам использовать сторонние библиотеки для сборки собственных проектов в соответствии с собственными потребностями.