πŸƒ ПишСм мСссСндТСр Π½Π° Go Π·Π° час: 7 простых шагов ΠΎΡ‚ эхо-сСрвСра ΠΊ асинхронному ΠΎΠ±ΠΌΠ΅Π½Ρƒ сообщСниями

Авторы Π±ΠΎΠ»ΡŒΡˆΠΈΠ½ΡΡ‚Π²Π° статСй ΠΏΠΎ сокСтным соСдинСниям Π² ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°Ρ… ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡ΠΈΠ²Π°ΡŽΡ‚ΡΡ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ эхо-сСрвСра. Π”Π°Π²Π°ΠΉΡ‚Π΅ Ρ€Π°Π·ΠΎΠ²ΡŒΠ΅ΠΌ эту Ρ‚Π΅ΠΌΡƒ ΠΈ Π·Π° 7 простых шагов сдСлаСм вмСстС ΠΊΠΎΠ½ΡΠΎΠ»ΡŒΠ½Ρ‹ΠΉ мСссСндТСр сообщСний.

Π¨Π°Π³ 1. Π˜Ρ‰Π΅ΠΌ ΠΊΠΎΠ΄ эхо-сСрвСра

Π’ΠΈΠΏΠΎΠ²ΠΎΠΉ эхо-сСрвСр, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π΄Π°Π» ΠΌΠ½Π΅ ΠΏΠ΅Ρ€Π²ΡƒΡŽ ссылку Yandex, описан Π² ΡΡ‚Π°Ρ‚ΡŒΠ΅ Β«Golang: простой сСрвСр TCP ΠΈ TCP-ΠΊΠ»ΠΈΠ΅Π½Ρ‚Β». Если Π²Ρ‹ Π½Π΅ ΠΈΠΌΠ΅Π΅Ρ‚Π΅ прСдставлСния, ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ сокСты ΠΈ соСдинСния, стоит Π΅Ρ‘ ΠΏΠΎΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ. Π˜ΡΡ…ΠΎΠ΄Π½Ρ‹ΠΉ ΠΊΠΎΠ΄ ΠΈΠ· этой ΡΡ‚Π°Ρ‚ΡŒΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΡΠΊΠ°Ρ‡Π°Ρ‚ΡŒ Ρ‚ΡƒΡ‚ ΠΈ ΠΆΠ΅Π»Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ сразу ΠΆΠ΅ Π΅Π³ΠΎ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ.

Если ΡΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ исходники ΠΈ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ Π² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Ρ… консолях ΠΊΠ»ΠΈΠ΅Π½Ρ‚ ΠΈ сСрвСр, Ρ‚ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠ±ΠΌΠ΅Π½ΠΈΠ²Π°Ρ‚ΡŒΡΡ сообщСниями. Π£ этого сСрвСра Π΅ΡΡ‚ΡŒ ΠΎΠ΄ΠΈΠ½ Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ нСдостаток: ΠΎΠ½ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ с ΠΎΠ΄Π½ΠΈΠΌ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΠΌ. ΠŸΠΎΠΏΡ€ΠΎΠ±ΡƒΠ΅ΠΌ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ Π² Π΅Ρ‰Π΅ ΠΎΠ΄Π½ΠΎΠΉ консоли Π½ΠΎΠ²Ρ‹ΠΉ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ ΠΈ ΡƒΠ²ΠΈΠ΄ΠΈΠΌ, ΠΊΠ°ΠΊ ΠΎΠ½Π° зависнСт. Π’ΠΎ ΠΆΠ΅ самоС Π±ΡƒΠ΄Π΅Ρ‚ ΠΈ с Ρ‡Π΅Ρ‚Π²Π΅Ρ€Ρ‚Ρ‹ΠΌ, ΠΈ с пятым ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΠΌ.

Π¨Π°Π³ 2. Π Π΅Π°Π»ΠΈΠ·ΡƒΠ΅ΠΌ ΠΏΡ€ΠΈΠ΅ΠΌ Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… соСдинСний

Π§Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΈΠ½ΡΡ‚ΡŒ нСсколько ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… соСдинСний, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ:

  • Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΏΡ€ΠΈΠ΅ΠΌΠ° соСдинСния conn.Accept() Π·Π°ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ Π΅Ρ‰Π΅ Π² ΠΎΠ΄ΠΈΠ½ Ρ†ΠΈΠΊΠ» for.
  • вСсь ΠΊΠΎΠ΄, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±Ρ‹Π» Π² Ρ†ΠΈΠΊΠ»Π΅, вынСсти Π² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ process().
  • Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ process() ΠΊΠ°ΠΊ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΡƒΡŽ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρƒ Π² Ρ†ΠΈΠΊΠ»Π΅ for сразу послС ΠΏΡ€ΠΈΠ΅ΠΌΠ° соСдинСния conn.Accept()
ΠŸΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅ ΠΎ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Π°Ρ… ΠΈ ΠΊΠ°Π½Π°Π»Π°Ρ… рассказываСтся Π² ΡΡ‚Π°Ρ‚ΡŒΠ΅ Β«ΠŸΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π² GoΒ». Π‘Ρ‚ΠΎΠΈΡ‚ с Π½Π΅ΠΉ ΠΎΠ·Π½Π°ΠΊΠΎΠΌΠΈΡ‚ΡŒΡΡ, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π½Π° этих ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠ°Ρ… основываСтся наш Π±ΡƒΠ΄ΡƒΡ‰ΠΈΠΉ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚.

Π’ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ Π½Π΅Π±ΠΎΠ»ΡŒΡˆΠΈΡ… ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ наш ΠΊΠΎΠ΄ ΠΏΡ€ΠΈΠΌΠ΅Ρ‚ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ Π²ΠΈΠ΄:

   // функция process запускаСтся ΠΊΠ°ΠΊ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Π°
    func process(conn net.Conn){
      // ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΠΌ, Ρ‡Ρ‚ΠΎ ΠΏΠ΅Ρ€Π΅Π΄ Π²Ρ‹Ρ…ΠΎΠ΄ΠΎΠΌ ΠΈΠ· Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, ΠΌΡ‹ Π·Π°ΠΊΡ€ΠΎΠ΅ΠΌ соСдинСниС
      defer conn.Close
      for {
         // Π‘ΡƒΠ΄Π΅ΠΌ ΠΏΡ€ΠΎΡΠ»ΡƒΡˆΠΈΠ²Π°Ρ‚ΡŒ всС сообщСния Ρ€Π°Π·Π΄Π΅Π»Π΅Π½Π½Ρ‹Π΅ \n
         message, _ := bufio.NewReader(conn).ReadString('\n')
         // РаспСчатываСм ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΎΠ΅ сообщСниС
         fmt.Print("Message Received:", string(message))
         // ΠžΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ Π½ΠΎΠ²ΡƒΡŽ строку ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Ρƒ
         conn.Write([]byte(message + "\n")){
        }
    } 

Код в main:

     // УстанавливаСм ΠΏΡ€ΠΎΡΠ»ΡƒΡˆΠΈΠ²Π°Π½ΠΈΠ΅ ΠΏΠΎΡ€Ρ‚Π°
    ln, _ := net.Listen("tcp", ":8081")
    // Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Ρ†ΠΈΠΊΠ»Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ соСдинСний
    for {    
      // ΠŸΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅ΠΌ входящСС соСдинСниС
      conn, _ := ln.Accept()
      // запускаСм Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ process(conn)   ΠΊΠ°ΠΊ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρƒ
      go process(conn)
    }
Π’Π½Π΅ΡˆΠ½ΠΈΠΉ Ρ†ΠΈΠΊΠ» (строки 31-36, ΠΊΠΎΠ΄ доступСн Π² Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΈ) Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Ρ‚ΡŒ входящСС соСдинСниС, Π° Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½ΠΈΠΉ Ρ†ΠΈΠΊΠ» (строки 15-19) Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ Π²Ρ…ΠΎΠ΄Π½Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅. Π˜ΡΡ…ΠΎΠ΄Π½Ρ‹ΠΉ ΠΊΠΎΠ΄ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° ΠΌΡ‹ Π½Π΅ мСняСм.

Если ΠΌΡ‹ запустим Π² ΠΎΠ΄Π½ΠΎΠΉ консоли сСрвСр, Π° Π² Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… Π΄Ρ€ΡƒΠ³ΠΈΡ… консолях ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π°, Ρ‚ΠΎ ΠΌΠΎΠΆΠ½ΠΎ Π²ΠΈΠ΄Π΅Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ сСрвСр ΠΌΠΎΠΆΠ΅Ρ‚ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ ΡƒΠΆΠ΅ нСсколько соСдинСний с ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π°ΠΌΠΈ ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎ. На самом Π΄Π΅Π»Π΅ ΠΎΠ½ ΠΈΡ… ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ асинхронно: спСрва ΠΎΠ΄ΠΈΠ½ запрос, ΠΏΠΎΡ‚ΠΎΠΌ Π΄Ρ€ΡƒΠ³ΠΎΠΉ, осущСствляя ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ ΠΌΠ΅ΠΆΠ΄Ρƒ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Π°ΠΌΠΈ.

Π¨Π°Π³ 3. ΠžΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅ΠΌ ошибки соСдинСний

Π”Π°Π²Π°ΠΉΡ‚Π΅ ΠΏΠΎΠΏΡ€ΠΎΠ±ΡƒΠ΅ΠΌ ΠΎΡ‚ΡΠΎΠ΅Π΄ΠΈΠ½ΠΈΡ‚ΡŒ ΠΎΠ΄ΠΈΠ½ ΠΈΠ· ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΠ², ΡƒΠ±ΠΈΠ² Π΅Π³ΠΎ процСсс: наш сСрвСр зациклится. Если Ρ‡Ρ‚ΠΎ-Π½ΠΈΠ±ΡƒΠ΄ΡŒ Π½Π°Π±Ρ€Π°Ρ‚ΡŒ Π² ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π΅, Ρ‚ΠΎ Π΄Π°Π½Π½Ρ‹Π΅ ΠΊΡƒΠ΄Π°-Ρ‚ΠΎ уходят, ΠΈ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π½ΠΈ ΠΎ Ρ‡Ρ‘ΠΌ Π½Π΅ ΠΏΠΎΠ΄ΠΎΠ·Ρ€Π΅Π²Π°Π΅Ρ‚.

ΠœΡ‹ Π·Π°Π±Ρ‹Π»ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ ошибки Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π°. Ѐункция Π²Ρ‹Π²ΠΎΠ΄Π° Π² сокСт Write ΠΈΠΌΠ΅Π΅Ρ‚ Π΄Π²Π° Π²Ρ‹Ρ…ΠΎΠ΄Π½Ρ‹Ρ… ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π°: ΠΊΠΎΠ»-Π²ΠΎ считанных Π±Π°ΠΉΡ‚ ΠΈ ΠΎΡˆΠΈΠ±ΠΊΡƒ:

data_len, err := conn.Write(b []byte)

Если ошибка Π½Π΅ пустая (Ρ‚.Π΅. Π½Π΅ Ρ€Π°Π²Π½Π° nil ), Π·Π½Π°Ρ‡ΠΈΡ‚ ΠΌΡ‹ Π½Π΅ смогли ΠΏΡ€ΠΈΠ½ΡΡ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅. Какая ошибка ΠΏΡ€ΠΎΠΈΠ·ΠΎΡˆΠ»Π°, ΠΌΠΎΠΆΠ½ΠΎ ΡƒΠ·Π½Π°Ρ‚ΡŒ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ err.Error()

Π—Π°ΠΌΠ΅Π½ΠΈΠΌ conn.Write(b []byte) Π½Π° ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ ΠΊΠΎΠ΄:

_ , err := conn.Write(b []byte)
if err != nil {
          fmt.Println(err.Error)
          break  // Π²Ρ‹Ρ…ΠΎΠ΄ΠΈΠΌ ΠΈΠ· Ρ†ΠΈΠΊΠ»Π° ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ
} 

Аналогичный ΠΊΠΎΠ΄ ΠΏΡ€ΠΎΠΏΠΈΡˆΠ΅ΠΌ Π² ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π΅. Π•Ρ‰Π΅ Π² ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π΅ отсутствуСт ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ΅ Π·Π°ΠΊΡ€Ρ‹Ρ‚ΠΈΠ΅ соСдинСния, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ срабатываСт ΠΏΡ€ΠΈ Π²Ρ‹Ρ…ΠΎΠ΄Π΅ ΠΈΠ· Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ defer conn.Close().

Если Π²Ρ‹ Π½Π΅ смогли внСсти измСнСния ΡΠ°ΠΌΠΎΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΠ½ΠΎ, Π³ΠΎΡ‚ΠΎΠ²Ρ‹ΠΉ ΠΊΠΎΠ΄ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠ΄Π³Π»ΡΠ΄Π΅Ρ‚ΡŒ Π½Π° GitHub.

Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΏΡ€ΠΈ Π·Π°ΠΊΡ€Ρ‹Ρ‚ΠΈΠ΅ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° ΠΈΠ»ΠΈ сСрвСра, Ρƒ нас Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π΄Π°Π²Π°Ρ‚ΡŒΡΡ сообщСниС:

write tcp 127.0.0.1:8081->127.0.0.1:40296: write: broken pipe

Π¨Π°Π³ 4. ΠŸΡ€ΠΎΡΡ‚ΠΎΠΉ ΠΏΡ€ΠΎΡ‚ΠΎΡ‚ΠΈΠΏ мСссСндТСра

К этому ΠΌΠΎΠΌΠ΅Π½Ρ‚Ρƒ ΠΌΡ‹ Π΄ΠΎΠΏΠΈΠ»ΠΈΠ»ΠΈ эхо-сСрвСр, Π° Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΎΡΡ‚Π°Π»ΠΎΡΡŒ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ простой ΠΈΠ· Π½Π΅Π³ΠΎ мСссСндТСр. ΠŸΡƒΡΡ‚ΡŒ Π»ΠΎΠ³ΠΈΠΊΠ° мСссСндТСра Π±ΡƒΠ΄Π΅Ρ‚ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ:

  • ΠšΠ»ΠΈΠ΅Π½Ρ‚ коннСктится ΠΊ сСрвСру ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ Π½ΠΎΠΌΠ΅Ρ€ сообщСния. КаТдай ΠΊΠ»ΠΈΠ΅Π½Ρ‚ ΠΈΠΌΠ΅Π΅Ρ‚ свой ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ Π½ΠΎΠΌΠ΅Ρ€.
  • ΠšΠ»ΠΈΠ΅Π½Ρ‚ отправляСт сообщСниС сСрвСру с ΡƒΠΊΠ°Π·Π°Π½ΠΈΠ΅ΠΌ Π½ΠΎΠΌΠ΅Ρ€Π° ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π°, ΠΊΠΎΠΌΡƒ адрСсовано это сообщСниС.
  • Π‘Π΅Ρ€Π²Π΅Ρ€ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ сообщСниС ΠΎΡ‚ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π°, Π΄Π΅ΠΊΠΎΠ΄ΠΈΡ€ΡƒΠ΅Ρ‚ Π΅Π³ΠΎ ΠΈ отправляСт Ρ‚ΠΎΠΌΡƒ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Ρƒ, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ адрСсовано это сообщСниС.
Нам ΠΎΡΡ‚Π°Π»ΠΎΡΡŒ ΡƒΡΠΎΠ²Π΅Ρ€ΡˆΠ΅Π½ΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ сСрвСр Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ, с ΠΊΠ°ΠΊΠΎΠ³ΠΎ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° Π±Ρ‹Π»ΠΎ ΠΎΡ‚ΠΏΡ€Π°Π²Π»Π΅Π½ΠΎ сообщСниС. Для простоты ΠΏΡƒΡΡ‚ΡŒ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π±ΡƒΠ΄Π΅Ρ‚ ΠΈΠΌΠ΅Ρ‚ΡŒ Π½ΠΎΠΌΠ΅Ρ€, ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ порядковому Π½ΠΎΠΌΠ΅Ρ€Ρƒ соСдинСния начиная с нуля (индСксы массивов Π² Go Π½Π°Ρ‡ΠΈΠ½Π°ΡŽΡ‚ΡΡ с нуля).

Π’Π²Π΅Π΄Π΅ΠΌ счСтчик входящих соСдинСний, Π° ΠΊΠ°ΠΆΠ΄ΠΎΠ΅ Π½ΠΎΠ²ΠΎΠ΅ соСдинСниС сохраним Π² xeΡˆΡ‚Π°Π±Π»ΠΈΡ†Π΅, ΠΎΡ€Π³Π°Π½ΠΈΠ·ΠΎΠ²Π°Π² Ρ‚Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ ΠΏΡƒΠ»:

conns := make( map[int] net.Conn, 1024)

КаТдоС соСдинСниС послС conn.Accept() ΠΌΡ‹ сохраним Π² conns, Π° Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ process() Π±ΡƒΠ΄Π΅ΠΌ ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Ρ‚ΡŒ вСсь ΠΏΡƒΠ» (Ρ…Π΅ΡˆΡ‚Π°Π±Π»ΠΈΡ†Ρƒ) ΠΈ Π½ΠΎΠΌΠ΅Ρ€ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ соСдинСния. Π’ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ соСдинСния process() ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΈΠΌΠ΅Ρ‚ΡŒ доступ ΠΊΠΎ всСм Π°ΠΊΡ‚ΠΈΠ²Π½Ρ‹ΠΌ соСдинСниям. НС Π·Π°Π±Ρ‹Π²Π°Π΅ΠΌ ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Ρ‚ΡŒ Π½Π° Π΅Π΄ΠΈΠ½ΠΈΡ†Ρƒ счСтчик Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΡ… соСдинСний.

Π’ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ process() ΠΌΡ‹ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅ΠΌ Π½Π΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ соСдинСниС, Π° ΠΏΡƒΠ» ΠΈ Π½ΠΎΠΌΠ΅Ρ€ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ соСдинСния. Π‘Π»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ, Ρ‡Ρ‚ΠΎΠ± ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ доступ ΠΊ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌΡƒ соСдинСнию, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π΅Π³ΠΎ Π²Π·ΡΡ‚ΡŒ ΠΈΠ· ΠΏΡƒΠ»Π°:

conn := conn[n]

Новый ΠΊΠΎΠ΄ сСрвСра:

func process(conns map[int]net.Conn, n int) {
  // ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ доступ ΠΊ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌΡƒ соСдинСнию
  conn := conns[n]
  // ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΠΌ, Ρ‡Ρ‚ΠΎ ΠΏΠ΅Ρ€Π΅Π΄ Π²Ρ‹Ρ…ΠΎΠ΄ΠΎΠΌ ΠΈΠ· Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, ΠΌΡ‹ Π·Π°ΠΊΡ€ΠΎΠ΅ΠΌ соСдинСниС
  defer conn.Close()
  for {
    // Π‘ΡƒΠ΄Π΅ΠΌ ΠΏΡ€ΠΎΡΠ»ΡƒΡˆΠΈΠ²Π°Ρ‚ΡŒ всС сообщСния Ρ€Π°Π·Π΄Π΅Π»Π΅Π½Π½Ρ‹Π΅ \n
    message, _ := bufio.NewReader(conn).ReadString('\n')
    // РаспСчатываСм ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΎΠ΅ сообщСниС
    fmt.Print("Message Received:", string(message))
    // ΠžΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ Π½ΠΎΠ²ΡƒΡŽ строку ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Ρƒ
    _, err := conn.Write([]byte(strconv.Itoa(n) + "->> " + message + "\n"))
    // Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅ΠΌ Π½Π° ΠΎΡˆΠΈΠ±ΠΊΡƒ
    if err != nil {
      fmt.Print(err.Error())
      break // Π²Ρ‹Ρ…ΠΎΠ΄ΠΈΠΌ ΠΈΠ· Ρ†ΠΈΠΊΠ»Π°
    }
  }
}
func main() {
  fmt.Println("Start server...")
  // создаСм ΠΏΡƒΠ» соСдинСний
  conns := make(map[int]net.Conn, 1024)
  i := 0
  // УстанавливаСм ΠΏΡ€ΠΎΡΠ»ΡƒΡˆΠΈΠ²Π°Π½ΠΈΠ΅ ΠΏΠΎΡ€Ρ‚Π°
  ln, _ := net.Listen("tcp", ":8081")
  // объвляСм ΠΏΡƒΠ» соСдинСний Π½Π° 1024 соСдинСния
  conns := make(map[int]net.Conn, 1024)
  // ЗапускаСм Ρ†ΠΈΠΊΠ» ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ соСдинСний
  for {
    // ΠŸΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅ΠΌ входящСС соСдинСниС
    conn, _ := ln.Accept()
    // сохраняСм соСдинСниС Π² ΠΏΡƒΠ»
    conns[i] = conn
    // запускаСм Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ process(conn)   ΠΊΠ°ΠΊ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρƒ
    go process(conns, i)
    i++
  }
}
ΠŸΠΎΠ»Π½Ρ‹ΠΉ ΠΊΠΎΠ΄ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡ‚ΠΈ Π² этом Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΈ. ΠŸΠΎΠΏΡ€ΠΎΠ±ΡƒΠ΅ΠΌ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ сСрвСр ΠΈ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ сообщСниС.

ΠŸΡ€ΠΈ тСстировании ΠΌΡ‹ Π²ΠΈΠ΄ΠΈΠΌ, Ρ‡Ρ‚ΠΎ Π² ΠΊΠ°ΠΆΠ΄ΠΎΠΌ ΠΎΡ‚Π²Π΅Ρ‚Π½ΠΎΠΌ сообщСнии сСрвСр Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Ρƒ Π½ΠΎΠΌΠ΅Ρ€ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ соСдинСния:

./client
Text to send: msg from 1
Message from server: 1->> msg from 1

Π¨Π°Π³ 5. РСализация ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° ΠΎΠ±ΠΌΠ΅Π½Π°

ΠžΡΡ‚Π°Π΅Ρ‚ΡΡ ΠΌΠ°Π»ΠΎΡΡ‚ΡŒ: ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ ΠΊΠ°ΠΊ, ΠΊΡ‚ΠΎ ΠΈ ΠΊΠΎΠΌΡƒ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΡ‚ΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ сообщСния. Π‘ΠΎΠ·Π΄Π°Π΄ΠΈΠΌ ΠΏΡ€ΠΎΡΡ‚Π΅ΠΉΡˆΠΈΠΉ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» ΠΎΠ±ΠΌΠ΅Π½Π°, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ ΠΏΠ΅Ρ€Π²Ρ‹Π΅ Π±Π°ΠΉΡ‚Ρ‹ сообщСния Π±ΡƒΠ΄ΡƒΡ‚ ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒ Π½ΠΎΠΌΠ΅Ρ€ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° ΠΈ тСкст Ρ‡Π΅Ρ€Π΅Π· ΠΏΡ€ΠΎΠ±Π΅Π».

ΠŸΡ€ΠΈΠΌΠ΅Ρ€:

2 ΠžΠΏΡ€Π°Π²Π»ΡΠ΅ΠΌ сообщСниС Π²Ρ‚ΠΎΡ€ΠΎΠΌΡƒ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Ρƒ

Для Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ этого ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ парсинг сообщСния. НомСр ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π°, ΠΌΡ‹ Π²Ρ‹Ρ‚Π°Ρ‰ΠΈΠΌ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ fmt.Scanf(), Π° само сообщСниС с использованиСм слайса:

// парсинг ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½ΠΎΠ³ΠΎ сообщСния
fmt.Sscanf(message, "%d", &clientNo) // ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈ Π½ΠΎΠΌΠ΅Ρ€ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π°
pos := strings.Index(message, " ") // нашли ΠΏΠΎΠ·ΠΈΡ†ΠΈΡŽ раздСлитСля
out_message := message[pos:] // взяли хвост сообщСниС послС ΠΏΡ€ΠΎΠ±Π΅Π»Π°

Π”Π°Π»ΡŒΡˆΠ΅ всС ΠΎΡ‡Π΅Π½ΡŒ просто: зная Π½ΠΎΠΌΠ΅Ρ€ соСдинСния (clientNo) ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π°, ΠΌΡ‹ Π±ΡƒΠ΄Π΅ΠΌ ΠΎΡ‚ΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ ΠΎΡ‚Π²Π΅Ρ‚ Π² Π½ΡƒΠΆΠ½ΠΎΠ΅ соСдинСниС. Π‘ΠΎΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅ Π±Ρ‹Π»ΠΎ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΎ, ΠΈ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΌΡ‹ Π²Ρ‹Π²ΠΎΠ΄ΠΈΠΌ, ΠΎΡ‚ ΠΊΠ°ΠΊΠΎΠ³ΠΎ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° ΠΎΠ½ΠΎ исходит:

conns[clientNo].Write([]byte(strconv.Itoa(clientNo) + "->> " + out_message + "\n"))
ЗапускаСм, провСряСм ΠΈ Π²ΠΈΠ΄ΠΈΠΌ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±Π°Π³ΠΈ. Если ΠΌΡ‹ направляСм сообщСниС самому сСбС, Ρ‚ΠΎ Π²Ρ€ΠΎΠ΄Π΅ Π±Ρ‹ всС Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚. Если ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ сообщСниС Π΄Ρ€ΡƒΠ³ΠΎΠΌΡƒ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Ρƒ, ΠΎΠ½ΠΎ Π³Π΄Π΅-Ρ‚ΠΎ тСряСтся, Π° Ссли этим ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΠΌ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ сообщСниС ΠΊΠΎΠΌΡƒ-Ρ‚ΠΎ Π΅Ρ‰Π΅, ΠΎΠ½ΠΎ появляСтся ΠΈΠ· Π½ΠΈΠΎΡ‚ΠΊΡƒΠ΄Π°. Π§Ρ‚ΠΎ ΠΆΠ΅ пошло Π½Π΅ Ρ‚Π°ΠΊ?

Π¨Π°Π³ 6. РаспараллСливаниС ΠΊΠΎΠ΄Π°

Наш ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ синхронно: послС отправлСния сообщСния ΠΎΠ½ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΡ‚ Π² Ρ€Π΅ΠΆΠΈΠΌ оТидания чтСния сокСта. ВсС Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ согласно Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΡƒ: записал ΠΈ ΠΆΠ΄ΠΈ ΠΎΡ‚Π²Π΅Ρ‚Π°. Если ΠΌΡ‹ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΠΌ сообщСниС самому сСбС, Ρ‚ΠΎ ΠΏΡ€ΠΈΠΌΠ΅ΠΌ Π΅Π³ΠΎ Π±Π΅Π· ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ. А Ссли ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΠΌ Π΄Ρ€ΡƒΠ³ΠΎΠΌΡƒ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Ρƒ, Ρ‚ΠΎ послС этого встаСм Π² Ρ€Π΅ΠΆΠΈΠΌ ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠΉ. Π’Ρ‚ΠΎΡ€ΠΎΠΉ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Ρ‚ΠΎΠΆΠ΅ стоит Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ оТидания ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ‚ нашС сообщСниС, Ρ‚ΠΎΠ»ΡŒΠΊΠΎ послС Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ сам Ρ‡Ρ‚ΠΎ-Π½ΠΈΠ±ΡƒΠ΄ΡŒ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚. Как ΠΆΠ΅ Π²Ρ‹ΠΉΡ‚ΠΈ ΠΈΠ· этой ситуации?

Π’Ρ‹Ρ…ΠΎΠ΄ довольно простой: Π½ΡƒΠΆΠ½ΠΎ Ρ‡Ρ‚Π΅Π½ΠΈΠ΅ ΠΈΠ· сокСта ΠΈ Ρ‡Ρ‚Π΅Π½ΠΈΠ΅ с консоли ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ асинхронными, Ρ‚.Π΅. ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π²Π²ΠΎΠ΄ ΠΈΠ· сокСта ΠΈ Π²Π²ΠΎΠ΄ ΠΈΠ· консоли Π½Π΅ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π»ΠΈ Π΄Ρ€ΡƒΠ³ Π΄Ρ€ΡƒΠ³Π°. Как Π³ΠΎΠ²ΠΎΡ€ΠΈΠ»ΠΎΡΡŒ Π²Ρ‹ΡˆΠ΅, Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‚ ΠΊΠΎΠ΄Ρƒ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ асинхронно. Π‘Π»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ, Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ Π·Π°ΠΏΡƒΡ‰Π΅Π½Ρ‹ Π΄Π²Π΅ Ρ€Π°Π·Π½Ρ‹Π΅ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹: ΠΎΠ΄Π½Π° Π΄ΠΎΠ»ΠΆΠ½Π° ΠΎΡΡƒΡ‰Π΅ΡΡ‚Π²Π»ΡΡ‚ΡŒ Ρ‡Ρ‚Π΅Π½ΠΈΠ΅ с консоли, Π° вторая – Ρ‡Ρ‚Π΅Π½ΠΈΠ΅ ΠΈΠ· сокСта.

ΠŸΠ΅Ρ€Π²Π°Ρ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Π° Ρ‡ΠΈΡ‚Π°Π΅Ρ‚ Π΄Π°Π½Π½Ρ‹Π΅ ΠΈΠ· сокСта, ΠΈ Ссли Π² сокСтС Π΅ΡΡ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅, Π²Ρ‹Π²ΠΎΠ΄ΠΈΡ‚ ΠΈΡ… Π½Π° ΠΏΠ΅Ρ‡Π°Ρ‚ΡŒ. Π§Ρ‚Π΅Π½ΠΈΠ΅ ΠΈ Π²Ρ‹Π²ΠΎΠ΄ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ Π·Π°ΠΊΠ»ΡŽΡ‡Π΅Π½Ρ‹ Π² Ρ†ΠΈΠΊΠ»:

// ΠΏΡ€ΠΈΠ΅ΠΌ Π΄Π°Π½Π½Ρ‹Ρ… ΠΈΠ· сокСта ΠΈ Π²Ρ‹Π²ΠΎΠ΄ Π½Π° ΠΏΠ΅Ρ‡Π°Ρ‚ΡŒ
func readSock(conn net.Conn ) {
    buf := make([]byte,256)
    for {
        readed_len, _ := conn.Read(buf)
        if readed_len > 0 {            
            fmt.Print(string(buf))
        }
    }
}

Π‘ΠΎ Π²Ρ‚ΠΎΡ€ΠΎΠΉ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½ΠΎΠΉ всС Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ слоТнСС, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ½Π° Π΄ΠΎΠ»ΠΆΠ½Π° ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅ Π² ΠΎΡΠ½ΠΎΠ²Π½ΡƒΡŽ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ. ΠŸΠΎΡ‡Π΅ΠΌΡƒ нСльзя сразу ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΈΡ… Π² сокСт, ΠΊΠ°ΠΊ это Π΄Π΅Π»Π°Π΅Ρ‚ пСрвая Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Π°? Π£Π²Ρ‹, опСрация conn.Write() – Π±Π»ΠΎΠΊΠΈΡ€ΡƒΡŽΡ‰Π°Ρ, ΠΈ Ссли ΠΌΡ‹ Ρ‚Π°ΠΊ сдСлаСм, Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅ΠΌ Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π°. ВсС Π±Π»ΠΎΠΊΠΈΡ€ΡƒΡŽΡ‰ΠΈΠ΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Π½ΡƒΠΆΠ½ΠΎ разнСсти ΠΏΠΎ Ρ€Π°Π·Π½Ρ‹ΠΌ асинхронным частям ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹.

// Π²Π²ΠΎΠ΄ Π΄Π°Π½Π½Ρ‹Ρ… с консоли ΠΈ Π²Ρ‹Π²ΠΎΠ΄ ΠΈΡ… Π² ΠΊΠ°Π½Π°Π»
func readConsole(ch chan string) {
    for {
        fmt.Print(">")
        line, _ := bufio.NewReader(os.Stdin).ReadString('\n')
        out :=line[:len(line)-1] // ΡƒΠ±ΠΈΡ€Π°Π΅ΠΌ символ Π²ΠΎΠ·Π²Ρ€Π°Ρ‚Π° ΠΊΠ°Ρ€Π΅Ρ‚ΠΊΠΈ
        ch <- out // отправляСм Π΄Π°Π½Π½Ρ‹Π΅ Π² ΠΊΠ°Π½Π°Π»
    }
}

Основная ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Π΄ΠΎΠ»ΠΆΠ½Π° Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ Π΄Π²Π΅ асинхронных Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹: Ρ‡Ρ‚Π΅Π½ΠΈΠ΅ с консоли ΠΈ ΠΈΠ· сокСта (Π² Ρ†ΠΈΠΊΠ»Π΅ Ρ‡ΠΈΡ‚Π°Ρ‚ΡŒ ΠΊΠ°Π½Π°Π» ΠΈ Ссли Π² Π½Π΅ΠΌ Π΅ΡΡ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅, Ρ‚ΠΎ Π·Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΈΡ… Π² сокСт). Π§Ρ‚ΠΎΠ±Ρ‹ нашС консольноС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π½Π΅ «съСло» всС рСсурсы CPU, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ввСсти Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ Π·Π°Π΄Π΅Ρ€ΠΆΠΊΡƒ: time.Sleep(time.Seconds * 2)

Π”ΠΎΠ»ΠΆΠ½ΠΎ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒΡΡ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π½ΠΎ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π΅:

func main(){
    ch := make(chan string)

    defer close(ch) // Π·Π°ΠΊΡ€Ρ‹Π²Π°Π΅ΠΌ ΠΊΠ°Π½Π°Π» ΠΏΡ€ΠΈ Π²Ρ‹Ρ…ΠΎΠ΄Π΅ ΠΈΠ· ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹

    conn, _ := net.Dial("tcp", "127.0.0.1:8080")

    go readConsole(ch)
    go readSock(conn)

    for {
        val, ok := <- ch
        if ok { // Ссли Π΅ΡΡ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅, Ρ‚ΠΎ ΠΈΡ… пишСм Π² сокСт

            _, err := conn .Write([]bytes(val))
            if err != nil {
                fmt.Println("Write:", err.Error())
                break
            }
        } else {
            // Π΄Π°Π½Π½Ρ‹Ρ… Π² ΠΊΠ°Π½Π°Π»Π΅ Π½Π΅Ρ‚, Π·Π°Π΄Π΅Ρ€ΠΆΠΊΠ° Π½Π° 2 сСкунды
            time.Sleep(time.Second * 2)
        }

    }
    fmt.Println("Finished...")
    conn.Close()
}

Π¨Π°Π³ 7. ΠŸΠΎΠ²Ρ‹ΡˆΠ°Π΅ΠΌ Π½Π°Π΄Π΅ΠΆΠ½ΠΎΡΡ‚ΡŒ выполнСния ΠΊΠΎΠ΄Π°

НашС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ ΠΏΡ€ΠΈ Π»ΡŽΠ±Ρ‹Ρ… Π²Ρ…ΠΎΠ΄Π½Ρ‹Ρ… Π΄Π°Π½Π½Ρ‹Ρ…, Π΄Π°ΠΆΠ΅ Ссли ΠΎΠ½ΠΈ Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½Ρ‹Π΅. Π•ΡΡ‚ΡŒ нСсколько простых ΠΏΡ€Π°Π²ΠΈΠ», ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ придСтся ΡΠΎΠ±Π»ΡŽΠ΄Π°Ρ‚ΡŒ ΠΏΡ€ΠΈ построСнии Π»ΡŽΠ±Ρ‹Ρ… ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ:

  • Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡΡ‚ΡŒ всС входящиС Π΄Π°Π½Π½Ρ‹Π΅ ΠΈ Ссли ΠΈΡ… Π΄Π»ΠΈΠ½Π½Π° большС ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°ΡŽΡ‰Π΅Π³ΠΎ Π±ΡƒΡ„Π΅Ρ€Π°, Ρ‚ΠΎ Π»ΠΈΠ±ΠΎ ΠΎΠ±Ρ€Π΅Π·Π°Ρ‚ΡŒ ΠΈΡ…, Π»ΠΈΠ±ΠΎ Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ;
  • Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ всС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π° Π½Π° Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ возникновСния ошибки.

НапримСр, Π² ΠΊΠΎΠ΄Π΅ Π±Ρ‹Π»ΠΎ ΠΌΠ½ΠΎΠ³ΠΎ сокращСний ΠΈ ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎ Π±Ρ‹Π»Π° ΠΎΠΏΡƒΡ‰Π΅Π½Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ conn.Accept() ΠΈ net.Dial():

    ls,err := conn.Accept()
    if err != nil {
        fmt.Println(err)
        panic("accept")
    }

Π’Π°ΠΊΠΆΠ΅ Π±Ρ‹Π» ΠΎΠΏΡƒΡ‰Π΅Π½ ΠΊΠΎΠ΄ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ объСма Π΄Π°Π½Π½Ρ‹Ρ… с консоли:

    // Π²Π²ΠΎΠ΄ Π΄Π°Π½Π½Ρ‹Ρ… с консоли
    for {
        fmt.Print(">")
        line, _ := bufio.NewReader(os.Stdin).ReadString('\n')
        if len(line) > 250 {
            fmt.Println("Error: message is very lagre")
            continue
        }
        ch <- b
    }    

ΠŸΠΎΡ‡Ρ‚ΠΈ Π³ΠΎΡ‚ΠΎΠ²ΠΎΠ΅ ΠΈ работоспособноС Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡ‚ΠΈ Π² Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΈ: Π²Π°ΠΌ остаСтся ΡΠ°ΠΌΠΎΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΠ½ΠΎ Π΄ΠΎΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ всСх ошибок Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π°. Если Π²ΠΎΠ·Π½ΠΈΠΊΠ½Π΅Ρ‚ ΠΆΠ΅Π»Π°Π½ΠΈΠ΅ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ pull request Π² Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΉ, Ρ‚ΠΎ я смогу ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ Π² коммСнтариях Π½Π° ошибки ΠΈΠ»ΠΈ просто ΠΏΠΎΡ…Π²Π°Π»ΠΈΡ‚ΡŒ. Π‘Π΄Π΅Π»Π°ΠΉΡ‚Π΅ свой ΠΊΠΎΠ΄ достояниСм общСствСнности. Π£Π΄Π°Ρ‡ΠΈ!

Π›Π£Π§Π¨Π˜Π• БВАВЬИ ПО Π’Π•ΠœΠ•

Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° программиста
23 ноября 2018

Go vs Python: ΠΈΠ·ΡƒΡ‡Π΅Π½ΠΈΠ΅ основ языка Go Π² сравнСнии с Python

Π­Ρ‚ΠΎ Π½Π΅ сорСвнованиС Π΄Π²ΡƒΡ… языков, Π° просто Π΅Ρ‰Π΅ ΠΎΠ΄ΠΈΠ½ способ обучСния. Рассмат...
admin
19 сСнтября 2018

TOП-3 языка программирования, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π½ΡƒΠΆΠ½ΠΎ Π²Ρ‹ΡƒΡ‡ΠΈΡ‚ΡŒ Π΄ΠΎ 2019

Π­Ρ‚ΠΎ Π½Π΅ просто Ρ‚Ρ€ΠΈ Π»ΡƒΡ‡ΡˆΠΈΡ… языка программирования, Π° Π² Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ смыслС ΠΏΠΎΠΏΡ‹Ρ‚...
Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° программиста
27 октября 2017

30 Π»ΡƒΡ‡ΡˆΠΈΡ… ΠΊΠ½ΠΈΠ³ для освоСния языка программирования Go

Π˜Ρ‰Π΅Ρ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΏΠΎ Go? ΠŸΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΠ΅ΠΌ 30 книг для освоСния языка программирования...