рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдХреЛрдб рдФрд░ рдХреЛрдб рдХреЗ рд▓рд┐рдП рдЯреЗрд╕реНрдЯ

рдЕрдЬрдЧрд░ рдФрд░ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЬреИрд╕реА рдЧрддрд┐рд╢реАрд▓ рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ, рдСрдкрд░реЗрд╢рди рдХреЗ рджреМрд░рд╛рди рд╕реАрдзреЗ рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рд╡рд┐рдзрд┐рдпреЛрдВ рдФрд░ рдХрдХреНрд╖рд╛рдУрдВ рдХреЛ рдмрджрд▓рдирд╛ рд╕рдВрднрд╡ рд╣реИред рдпрд╣ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ - рдЖрдк рдмрд╕ "рдкреИрдЪ" рдбрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдЗрд╕ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рднрд╛рд░реА рдпрд╛ рдЕрдирд╛рд╡рд╢реНрдпрдХ рддрд░реНрдХ рдХреЛ рдмрд╛рд╣рд░ рдХрд░ рджреЗрдЧрд╛ред


рд▓реЗрдХрд┐рди C ++ рдореЗрдВ рдХреНрдпрд╛ рдХрд░рдирд╛ рд╣реИ? рдЬрд╛рдУ? рдЬрд╛рд╡рд╛? рдЗрди рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ, рдордХреНрдЦреА рдкрд░ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдХреЛрдб рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рдкреИрдЪ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрд▓рдЧ рдЙрдкрдХрд░рдг рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред


рдРрд╕реЗ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдЖрдкрдХреЛ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдХреЛрдб рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП рддрд╛рдХрд┐ рдЗрд╕рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рдЬрд╛рдПред рдпрд╣ рдХреЗрд╡рд▓ рдЖрдкрдХреЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ 100% рдХрд╡рд░реЗрдЬ рджреЗрдЦрдиреЗ рдХреА рдПрдХ рдЙрдиреНрдорддреНрдд рдЗрдЪреНрдЫрд╛ рдирд╣реАрдВ рд╣реИред рдпрд╣ рд╕рдорд░реНрдерд┐рдд рдФрд░ рдЧреБрдгрд╡рддреНрддрд╛ рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдХреА рджрд┐рд╢рд╛ рдореЗрдВ рдПрдХ рдХрджрдо рд╣реИред


рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рдореИрдВ рдкрд░реАрдХреНрд╖рдг рдпреЛрдЧреНрдп рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдХреЗ рдкреАрдЫреЗ рдореБрдЦреНрдп рд╡рд┐рдЪрд╛рд░реЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛ рдФрд░ рджрд┐рдЦрд╛рдКрдВрдЧрд╛ рдХрд┐ рдХреИрд╕реЗ рдЙрдиреНрд╣реЗрдВ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдкреНрд░реЛрдЧреНрд░рд╛рдо рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред


рдЕрдзреВрд░рд╛ рдХрд╛рд░реНрдпрдХреНрд░рдо


рд╣рдо рд╡реАрдХреЗ рдПрдкреАрдЖрдИ рдХреЗ рд▓рд┐рдП рдЕрдиреБрд░реЛрдз рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд░рд▓ рдХрд╛рд░реНрдпрдХреНрд░рдо рд▓рд┐рдЦреЗрдВрдЧреЗред рдпрд╣ рдПрдХ рдХрд╛рдлреА рд╕рд░рд▓ рдХрд╛рд░реНрдпрдХреНрд░рдо рд╣реИ рдЬреЛ рдПрдХ рдЕрдиреБрд░реЛрдз рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ, рдЗрд╕реЗ рдмрдирд╛рддрд╛ рд╣реИ, рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдкрдврд╝рддрд╛ рд╣реИ, JSON рд╕реЗ рдПрдХ рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЛ рдбреАрдХреЛрдб рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдкрд░рд┐рдгрд╛рдо рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИред


package main import ( "encoding/json" "fmt" "io/ioutil" "net/http" "net/url" ) const token = "token here" func main() { //     var requestURL = fmt.Sprintf( "https://api.vk.com/method/%s?&access_token=%s&v=5.95", "users.get", token, ) //   resp, err := http.PostForm(requestURL, nil) //   if err != nil { fmt.Println(err) return } //       defer resp.Body.Close() //     body, err := ioutil.ReadAll(resp.Body) //   if err != nil { fmt.Println(err) return } //      var result struct { Response []struct { ID int `json:"id"` FirstName string `json:"first_name"` LastName string `json:"last_name"` } `json:"response"` } //        err = json.Unmarshal(body, &result) //   if err != nil { fmt.Println(err) return } // ,    if len(result.Response) < 1 { fmt.Println("No values in response array") return } //    fmt.Printf( "Your id: %d\nYour full name: %s %s\n", result.Response[0].ID, result.Response[0].FirstName, result.Response[0].LastName, ) } 

рд╣рдорд╛рд░реЗ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рдкреЗрд╢реЗрд╡рд░реЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ, рд╣рдордиреЗ рддрдп рдХрд┐рдпрд╛ рдХрд┐ рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред рдПрдХ рдкрд░реАрдХреНрд╖рдг рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдВ ...


 package main import ( "testing" ) func Test_Main(t *testing.T) { main() } 

рдпрд╣ рдмрд╣реБрдд рдЖрдХрд░реНрд╖рдХ рдирд╣реАрдВ рд▓рдЧреЗрдЧрд╛ред рдпрд╣ рдЪреЗрдХ рдПрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛ рдПрдХ рд╕рд░рд▓ рд▓реЙрдиреНрдЪ рд╣реИ рдЬрд┐рд╕реЗ рд╣рдо рдкреНрд░рднрд╛рд╡рд┐рдд рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╣рдо рдиреЗрдЯрд╡рд░реНрдХ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХреЛ рдмрд╛рд╣рд░ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд╡рд┐рднрд┐рдиреНрди рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рдВрдЪрд╛рд▓рди рдХреА рдЬрд╛рдВрдЪ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рд╕рддреНрдпрд╛рдкрди рдХреЗ рд▓рд┐рдП рдЯреЛрдХрди рдХреА рдЬрдЧрд╣ рд╡рд┐рдлрд▓ рд╣реЛ рдЬрд╛рдПрдЧреАред рдЖрдЗрдП рдЬрд╛рдирдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЛ рдХреИрд╕реЗ рдмреЗрд╣рддрд░ рдмрдирд╛рдпрд╛ рдЬрд╛рдПред


рдирд┐рд░реНрднрд░рддрд╛ рдЗрдВрдЬреЗрдХреНрд╢рди рдкреИрдЯрд░реНрди


рдкрд╣рд▓реЗ рдЖрдкрдХреЛ "рдирд┐рд░реНрднрд░рддрд╛ рдЗрдВрдЬреЗрдХреНрд╢рди" рдкреИрдЯрд░реНрди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред


 type VKClient struct { Token string } func (client VKClient) ShowUserInfo() { var requestURL = fmt.Sprintf( "https://api.vk.com/method/%s?&access_token=%s&v=5.95", "users.get", client.Token, ) // ... } 

рдПрдХ рд╕рдВрд░рдЪрдирд╛ рдХреЛ рдЬреЛрдбрд╝рдХрд░, рд╣рдордиреЗ рдЖрд╡реЗрджрди рдХреЗ рд▓рд┐рдП рдПрдХ рдирд┐рд░реНрднрд░рддрд╛ (рдПрдХреНрд╕реЗрд╕ рдХреБрдВрдЬреА) рдмрдирд╛рдИ, рдЬрд┐рд╕реЗ рд╡рд┐рднрд┐рдиреНрди рд╕реНрд░реЛрддреЛрдВ рд╕реЗ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬреЛ "рд╡рд╛рдпрд░реНрдб" рдореВрд▓реНрдпреЛрдВ рд╕реЗ рдмрдЪрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдкрд░реАрдХреНрд╖рдг рдХреЛ рд╕рд░рд▓ рдХрд░рддрд╛ рд╣реИред


 package example import ( "testing" ) const workingToken = "workingToken" func Test_ShowUserInfo_Successful(t *testing.T) { client := VKClient{workingToken} client.ShowUserInfo() } func Test_ShowUserInfo_EmptyToken(t *testing.T) { client := VKClient{""} client.ShowUserInfo() } 

рд╕реВрдЪрдирд╛ рдФрд░ рдЗрд╕рдХреЗ рдЖрдЙрдЯрдкреБрдЯ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рдкреГрдердХреНрдХрд░рдг


рдЕрдм рдХреЗрд╡рд▓ рдПрдХ рд╡реНрдпрдХреНрддрд┐ рдПрдХ рдЧрд▓рддреА рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рдЙрд╕рдХреЗ рдмрд╛рдж рд╣реА рдЕрдЧрд░ рд╡рд╣ рдЬрд╛рдирддрд╛ рд╣реИ рдХрд┐ рдирд┐рд╖реНрдХрд░реНрд╖ рдХреНрдпрд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдХрд┐ рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рд╕реАрдзреЗ рдЖрдЙрдЯрдкреБрдЯ рд╕реНрдЯреНрд░реАрдо рдкрд░ рдЖрдЙрдЯрдкреБрдЯ рди рдХрд░реЗрдВ, рд▓реЗрдХрд┐рди рдЬрд╛рдирдХрд╛рд░реА рдФрд░ рдЗрд╕рдХреЗ рдЖрдЙрдЯрдкреБрдЯ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрд▓рдЧ-рдЕрд▓рдЧ рддрд░реАрдХреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдирд╛ред рдЗрди рджреЛ рд╕реНрд╡рддрдВрддреНрд░ рднрд╛рдЧреЛрдВ рдХреЛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдирд╛ рдФрд░ рдмрдирд╛рдП рд░рдЦрдирд╛ рдЖрд╕рд╛рди рд╣реЛрдЧрд╛ред


рдЖрдЗрдП GetUserInfo() рд╡рд┐рдзрд┐ рдмрдирд╛рдПрдВ, рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЬрд╛рдирдХрд╛рд░реА рдФрд░ рдПрдХ рддреНрд░реБрдЯрд┐ (рдпрджрд┐ рдРрд╕рд╛ рд╣реБрдЖ) рдХреЗ рд╕рд╛рде рдПрдХ рд╕рдВрд░рдЪрдирд╛ рд▓реМрдЯрд╛рдПрдЧрд╛ред рдЪреВрдВрдХрд┐ рдпрд╣ рд╡рд┐рдзрд┐ рдХреБрдЫ рднреА рдЖрдЙрдЯрдкреБрдЯ рдирд╣реАрдВ рдХрд░рддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣реЛрдиреЗ рд╡рд╛рд▓реА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдЖрдЙрдЯрдкреБрдЯ рдХреЗ рдмрд┐рдирд╛ рдЖрдЧреЗ рдкреНрд░реЗрд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рддрд╛рдХрд┐ рдбреЗрдЯрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╡рд╛рд▓реЗ рдХреЛрдб рд╕реНрдерд┐рддрд┐ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛ рд╕рдХреЗрдВред


 type UserInfo struct { ID int `json:"id"` FirstName string `json:"first_name"` LastName string `json:"last_name"` } func (client VKClient) GetUserInfo() (UserInfo, error) { var requestURL = fmt.Sprintf( "https://api.vk.com/method/%s?&access_token=%s&v=5.95", "users.get", client.Token, ) resp, err := http.PostForm(requestURL, nil) if err != nil { return UserInfo{}, err } // ... var result struct { Response []UserInfo `json:"response"` } // ... return result.Response[0], nil } 

ShowUserInfo() рдмрджрд▓реЗрдВ рддрд╛рдХрд┐ рд╡рд╣ GetUserInfo() рдХрд╛ рдЙрдкрдпреЛрдЧ GetUserInfo() рдФрд░ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рд╣реИрдВрдбрд▓ рдХрд░реЗред


 func (client VKClient) ShowUserInfo() { userInfo, err := client.GetUserInfo() if err != nil { fmt.Println(err) return } fmt.Printf( "Your id: %d\nYour full name: %s %s\n", userInfo.ID, userInfo.FirstName, userInfo.LastName, ) } 

рдЕрдм, рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ, рдЖрдк рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рд╕рд░реНрд╡рд░ рд╕реЗ рд╕рд╣реА рдЙрддреНрддрд░ рдкреНрд░рд╛рдкреНрдд рд╣реБрдЖ рд╣реИ, рдФрд░ рдпрджрд┐ рдЯреЛрдХрди рдЧрд▓рдд рд╣реИ, рддреЛ рдПрдХ рддреНрд░реБрдЯрд┐ рд╡рд╛рдкрд╕ рдЖ рдЬрд╛рддреА рд╣реИред


 func Test_GetUserInfo_Successful(t *testing.T) { client := VKClient{workingToken} userInfo, err := client.GetUserInfo() if err != nil { t.Fatal(err) } if userInfo.ID == 0 { t.Fatal("ID is empty") } if userInfo.FirstName == "" { t.Fatal("FirstName is empty") } if userInfo.LastName == "" { t.Fatal("LastName is empty") } } func Test_ShowUserInfo_EmptyToken(t *testing.T) { client := VKClient{""} _, err := client.GetUserInfo() if err == nil { t.Fatal("Expected error but found <nil>") } if err.Error() != "No values in response array" { t.Fatalf(`Expected "No values in response array", but found "%s"`, err) } } 

рдореМрдЬреВрджрд╛ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЖрдкрдХреЛ ShowUserInfo() рд╡рд┐рдзрд┐ рдХреЗ рд▓рд┐рдП рдирдП рдкрд░реАрдХреНрд╖рдг рдЬреЛрдбрд╝рдиреЗ рд╣реЛрдВрдЧреЗред


 func Test_ShowUserInfo(t *testing.T) { client := VKClient{workingToken} client.ShowUserInfo() } func Test_ShowUserInfo_WithError(t *testing.T) { client := VKClient{""} client.ShowUserInfo() } 

рдХрд╕реНрдЯрдо рд╡рд┐рдХрд▓реНрдк


ShowUserInfo() рд▓рд┐рдП рдЯреЗрд╕реНрдЯ рдЬреЛ рд╣рдо рд╢реБрд░реВ рд╕реЗ рджреВрд░ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ рдЬреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╡рд┐рдзрд┐ рдХрд╛ рдПрдХрдорд╛рддреНрд░ рдмрд┐рдВрджреБ рдорд╛рдирдХ рдЖрдЙрдЯрдкреБрдЯ рд╕реНрдЯреНрд░реАрдо рдХреЛ рдЬрд╛рдирдХрд╛рд░реА рдЖрдЙрдЯрдкреБрдЯ рдХрд░рдирд╛ рд╣реИред рдПрдХ рддрд░рдл, рдЖрдк os.Stdout рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЖрдЙрдЯрдкреБрдЯ рдХреА рдЬрд╛рдВрдЪ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╣ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдирд┐рд░рд░реНрдердХ рд╕рдорд╛рдзрд╛рди рдХреА рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ рдЬрдм рдЖрдк рдЕрдзрд┐рдХ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рдврдВрдЧ рд╕реЗ рдХрд╛рд░реНрдп рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред


fmt.Printf рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп, рдЖрдк fmt.Printf рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдЖрдкрдХреЛ рдХрд┐рд╕реА рднреА io.Writer рдЖрдЙрдЯрдкреБрдЯ рдХреЗ рд▓рд┐рдП рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред os.Stdout рдЗрд╕ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рд╣рдореЗрдВ fmt.Printf(text) рдХреЛ fmt.Fprintf(os.Stdout, text) рд╕реЗ рдмрджрд▓рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЙрд╕рдХреЗ рдмрд╛рдж, рд╣рдо os.Stdout рдХреЛ рдПрдХ рдЕрд▓рдЧ рдлрд╝реАрд▓реНрдб рдореЗрдВ рд░рдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рд╕реЗ рд╡рд╛рдВрдЫрд┐рдд рдорд╛рдиреЛрдВ рдкрд░ рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ (рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд▓рд┐рдП - рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ, рдХрд╛рдо рдХреЗ рд▓рд┐рдП - рдПрдХ рдорд╛рдирдХ рдЖрдЙрдЯрдкреБрдЯ рд╕реНрдЯреНрд░реАрдо)ред


рдЪреВрдВрдХрд┐ рдЖрдЙрдЯрдкреБрдЯ рдХреЗ рд▓рд┐рдП рд░рд╛рдЗрдЯрд░ рдмрджрд▓рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╢рд╛рдпрдж рд╣реА рдХрднреА рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдореБрдЦреНрдп рд░реВрдк рд╕реЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд▓рд┐рдП, рдпрд╣ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди рд╕реЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИред рдЬрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЗрд╕рдХреЗ рд▓рд┐рдП рдпрд╣ рдХрд░реЗрдВрдЧреЗ - VKClient рдкреНрд░рдХрд╛рд░ рдХреЛ VKClient рдирд┐рд░реНрдпрд╛рдд рдпреЛрдЧреНрдп рдмрдирд╛рдПрдВ рдФрд░ рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рдирд┐рд░реНрдорд╛рддрд╛ рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рдПрдВред


 type vkClient struct { Token string OutputWriter io.Writer } func CreateVKClient(token string) vkClient { return vkClient{ token, os.Stdout, } } 

ShowUserInfo() рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ, рд╣рдо Print рдХреЙрд▓ рдХреЛ Fprintf рд╕рд╛рде Fprintf ред


 func (client vkClient) ShowUserInfo() { userInfo, err := client.GetUserInfo() if err != nil { fmt.Fprintf(client.OutputWriter, err.Error()) return } fmt.Fprintf( client.OutputWriter, "Your id: %d\nYour full name: %s %s\n", userInfo.ID, userInfo.FirstName, userInfo.LastName, ) } 

рдЕрдм рдЖрдкрдХреЛ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рддрд╛рдХрд┐ рд╡реЗ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЧреНрд░рд╛рд╣рдХ рдмрдирд╛рдПрдВ рдФрд░ рдЬрд╣рд╛рдВ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ, рдПрдХ рдФрд░ рд▓реЗрдЦрдХ рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВред


 func Test_ShowUserInfo(t *testing.T) { client := CreateVKClient(workingToken) buffer := bytes.NewBufferString("") client.OutputWriter = buffer client.ShowUserInfo() result, _ := ioutil.ReadAll(buffer) matched, err := regexp.Match( `Your id: \d+\nYour full name: [^\n]+\n`, result, ) if err != nil { t.Fatal(err) } if !matched { t.Fatalf(`Expected match but failed with "%s"`, result) } } func Test_ShowUserInfo_WithError(t *testing.T) { client := CreateVKClient("") buffer := bytes.NewBufferString("") client.OutputWriter = buffer client.ShowUserInfo() result, _ := ioutil.ReadAll(buffer) if string(result) != "No values in response array" { t.Fatal("Wrong error") } } 

рдкреНрд░рддреНрдпреЗрдХ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдЬрд╣рд╛рдВ рд╣рдо рдХреБрдЫ рдЙрддреНрдкрд╛рджрди рдХрд░рддреЗ рд╣реИрдВ, рд╣рдо рдПрдХ рдмрдлрд░ рдмрдирд╛рддреЗ рд╣реИрдВ рдЬреЛ рдПрдХ рдорд╛рдирдХ рдЖрдЙрдЯрдкреБрдЯ рд╕реНрдЯреНрд░реАрдо рдХреА рднреВрдорд┐рдХрд╛ рдирд┐рднрд╛рдПрдЧрд╛ред рдлрд╝рдВрдХреНрд╢рди рдирд┐рд╖реНрдкрд╛рджрд┐рдд рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж, рдпрд╣ рдЬрд╛рдБрдЪ рдХреА рдЬрд╛рддреА рд╣реИ рдХрд┐ рдкрд░рд┐рдгрд╛рдо рд╣рдорд╛рд░реА рдЕрдкреЗрдХреНрд╖рд╛рдУрдВ рдХреЗ рдЕрдиреБрд░реВрдк рд╣реИрдВ - рдирд┐рдпрдорд┐рдд рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐рдпреЛрдВ рдХреА рд╕рд╣рд╛рдпрддрд╛ рд╕реЗ рдпрд╛ рд╕рд╛рдзрд╛рд░рдг рддреБрд▓рдирд╛ рдХреЗ рд╕рд╛рдеред


рдореИрдВ рдирд┐рдпрдорд┐рдд рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреНрдпреЛрдВ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ? рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдХрд┐рд╕реА рднреА рд╡реИрдз рдЯреЛрдХрди рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬреЛ рдореИрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЖрдИрдбреА рдХреА рдкрд░рд╡рд╛рд╣ рдХрд┐рдП рдмрд┐рдирд╛ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЛ рдкреНрд░рджрд╛рди рдХрд░реЗрдЧрд╛ред


рдирд┐рд░реНрднрд░рддрд╛ рдЗрдВрдЬреЗрдХреНрд╢рди рдкреИрдЯрд░реНрди - 2


рдлрд┐рд▓рд╣рд╛рд▓, рдХрд╛рд░реНрдпрдХреНрд░рдо рдореЗрдВ 86.4% рдХрд╛ рдХрд╡рд░реЗрдЬ рд╣реИред 100% рдХреНрдпреЛрдВ рдирд╣реАрдВ? рд╣рдо http.PostForm() , ioutil.ReadAll() рдФрд░ json.Unmarshal() рд╕реЗ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдирд╣реАрдВ рднрдбрд╝рдХрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рд╣рдо рдкреНрд░рддреНрдпреЗрдХ " return UserInfo, err ioutil.ReadAll() , ioutil.ReadAll() " рдХреА рдЬрд╛рдВрдЪ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред


рд╕реНрдерд┐рддрд┐ рдкрд░ рдЦреБрдж рдХреЛ рдФрд░ рднреА рдЕрдзрд┐рдХ рдирд┐рдпрдВрддреНрд░рдг рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬрд┐рд╕рдХреЗ рддрд╣рдд http.Client рдлрд┐рдЯ рд╣реЛрдЧрд╛, рдЬрд┐рд╕рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди vkClient рдореЗрдВ рд╣реЛрдЧрд╛, рдФрд░ рдиреЗрдЯрд╡рд░реНрдХ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рд╣рдорд╛рд░реЗ рд▓рд┐рдП, рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдореЗрдВ, рдХреЗрд╡рд▓ рдПрдХ рд╡рд┐рдзрд┐ PostForm - PostForm ред


 type Networker interface { PostForm(string, url.Values) (*http.Response, error) } type vkClient struct { Token string OutputWriter io.Writer Networker Networker } func CreateVKClient(token string) vkClient { return vkClient{ token, os.Stdout, &http.Client{}, } } 

рдЗрд╕ рддрд░рд╣ рдХреЗ рдХрджрдо рд╕реЗ рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ рдиреЗрдЯрд╡рд░реНрдХ рд╕рдВрдЪрд╛рд▓рди рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╕рдорд╛рдкреНрдд рд╣реЛ рдЬрд╛рддреА рд╣реИред рдЕрдм рд╣рдо рдХреЗрд╡рд▓ рдирдХрд▓реА Networker рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ VKontakte рд╕реЗ рдЕрдкреЗрдХреНрд╖рд┐рдд рдбреЗрдЯрд╛ рд╡рд╛рдкрд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдмреЗрд╢рдХ, рдЙрди рдкрд░реАрдХреНрд╖рдгреЛрдВ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рди рдХрд░реЗрдВ рдЬреЛ рд╕рд░реНрд╡рд░ рд╕реЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рдЬрд╛рдВрдЪ рдХрд░реЗрдВрдЧреЗ, рд▓реЗрдХрд┐рди рдкреНрд░рддреНрдпреЗрдХ рдкрд░реАрдХреНрд╖рдг рдореЗрдВ рдЕрдиреБрд░реЛрдз рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред


рд╣рдо рдирдХрд▓реА Networker рдФрд░ Reader рд▓рд┐рдП рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдмрдирд╛рдПрдВрдЧреЗ, рддрд╛рдХрд┐ рд╣рдо рдкреНрд░рддреНрдпреЗрдХ рдорд╛рдорд▓реЗ рдореЗрдВ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░ рд╕рдХреЗрдВ - рдЕрдиреБрд░реЛрдз рдкрд░, рдЬрдм рд╢рд░реАрд░ рдХреЛ рдкрдврд╝рдиреЗ рдФрд░ deserialization рдХреЗ рджреМрд░рд╛рдиред рдпрджрд┐ рд╣рдо PostForm рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╕рдордп рдПрдХ рддреНрд░реБрдЯрд┐ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдЗрд╕реЗ рдЗрд╕ рд╡рд┐рдзрд┐ рдореЗрдВ рд╡рд╛рдкрд╕ рдХрд░ рджреЗрддреЗ рд╣реИрдВред рдЕрдЧрд░ рд╣рдо рдЧрд▓рддреА рдЪрд╛рд╣рддреЗ рд╣реИрдВ
рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдмреЙрдбреА рдХреЛ рдкрдврд╝рддреЗ рд╕рдордп - рдПрдХ рдирдХрд▓реА Reader рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдЬреЛ рдПрдХ рддреНрд░реБрдЯрд┐ рдлреЗрдВрдХ рджреЗрдЧрд╛ред рдФрд░ рдЕрдЧрд░ рд╣рдореЗрдВ deserialization рдХреЗ рджреМрд░рд╛рди рд╕реНрд╡рдпрдВ рдХреЛ рдкреНрд░рдХрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддреНрд░реБрдЯрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рддреЛ рд╣рдо рд╢рд░реАрд░ рдореЗрдВ рдПрдХ рдЦрд╛рд▓реА рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рд╕рд╛рде рдЙрддреНрддрд░ рджреЗрддреЗ рд╣реИрдВред рдпрджрд┐ рд╣рдо рдХреЛрдИ рддреНрд░реБрдЯрд┐ рдирд╣реАрдВ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдХреЗрд╡рд▓ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╕рд╛рдордЧреНрд░рд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рд╢рд░реАрд░ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рддреЗ рд╣реИрдВред


 type fakeReader struct{} func (fakeReader) Read(p []byte) (n int, err error) { return 0, errors.New("Error on read") } type fakeNetworker struct { ErrorOnPostForm bool ErrorOnBodyRead bool ErrorOnUnmarchal bool RawBody string } func (fn *fakeNetworker) PostForm(string, url.Values) (*http.Response, error) { if fn.ErrorOnPostForm { return nil, fmt.Errorf("Error on PostForm") } if fn.ErrorOnBodyRead { return &http.Response{Body: ioutil.NopCloser(fakeReader{})}, nil } if fn.ErrorOnUnmarchal { fakeBody := ioutil.NopCloser(bytes.NewBufferString("")) return &http.Response{Body: fakeBody}, nil } fakeBody := ioutil.NopCloser(bytes.NewBufferString(fn.RawBody)) return &http.Response{Body: fakeBody}, nil } 

рдкреНрд░рддреНрдпреЗрдХ рд╕рдорд╕реНрдпрд╛ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рдкрд░реАрдХреНрд╖рдг рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред рд╡реЗ рдЖрд╡рд╢реНрдпрдХ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдХреЗ рд╕рд╛рде рдирдХрд▓реА Networker рдмрдирд╛рдПрдВрдЧреЗ, рдЬрд┐рд╕рдХреЗ рдЕрдиреБрд╕рд╛рд░ рд╡рд╣ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдмрд┐рдВрджреБ рдкрд░ рдПрдХ рддреНрд░реБрдЯрд┐ рдлреЗрдВрдХ рджреЗрдЧрд╛ред рдЙрд╕рдХреЗ рдмрд╛рдж, рд╣рдо рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдЪреЗрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣рддреЗ рд╣реИрдВ рдФрд░ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдХреЛрдИ рддреНрд░реБрдЯрд┐ рд╣реБрдИ рд╣реИ, рдФрд░ рд╣рдореЗрдВ рдЗрд╕ рддреНрд░реБрдЯрд┐ рдХреА рдЙрдореНрдореАрдж рд╣реИред


 func Test_GetUserInfo_ErrorOnPostForm(t *testing.T) { client := CreateVKClient(workingToken) client.Networker = &fakeNetworker{ErrorOnPostForm: true} _, err := client.GetUserInfo() if err == nil { t.Fatal("Expected error but none found") } if err.Error() != "Error on PostForm" { t.Fatalf(`Expected "Error on PostForm" but got "%s"`, err.Error()) } } func Test_GetUserInfo_ErrorOnBodyRead(t *testing.T) { client := CreateVKClient(workingToken) client.Networker = &fakeNetworker{ErrorOnBodyRead: true} _, err := client.GetUserInfo() if err == nil { t.Fatal("Expected error but none found") } if err.Error() != "Error on read" { t.Fatalf(`Expected "Error on read" but got "%s"`, err.Error()) } } func Test_GetUserInfo_ErrorOnUnmarchal(t *testing.T) { client := CreateVKClient(workingToken) client.Networker = &fakeNetworker{ErrorOnUnmarchal: true} _, err := client.GetUserInfo() if err == nil { t.Fatal("Expected error but none found") } const expectedError = "unexpected end of JSON input" if err.Error() != expectedError { t.Fatalf(`Expected "%s" but got "%s"`, expectedError, err.Error()) } } 

RawBody рдлрд╝реАрд▓реНрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ, RawBody рдиреЗрдЯрд╡рд░реНрдХ рдЕрдиреБрд░реЛрдзреЛрдВ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВ (рдмрд╕ рд╣рдо рдЬреЛ VKontakte рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЙрдореНрдореАрдж рдХрд░рддреЗ рд╣реИрдВ) рд▓реМрдЯрд╛рдПрдВред рдкрд░реАрдХреНрд╖рдг рдХреЗ рджреМрд░рд╛рди рдпрд╛ рдкрд░реАрдХреНрд╖рдг рдХреА рдЧрддрд┐ рдмрдврд╝рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХреНрд╡реЗрд░реА рдХреА рд╕реАрдорд╛рдУрдВ рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред


рдкрд░рд┐рдгрд╛рдо


рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд╕рднреА рд╕рдВрдЪрд╛рд▓рди рдХреЗ рдмрд╛рдж, рд╣рдореЗрдВ 91 рд▓рд╛рдЗрдиреЛрдВ рдХреА рд▓рдВрдмреА (рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреА io.Writer рд▓рд╛рдЗрдиреЗрдВ) рдХрд╛ рдкреИрдХреЗрдЬ рдорд┐рд▓рд╛, рдЬреЛ рдХрд┐рд╕реА рднреА io.Writer рдХреЛ рдЖрдЙрдЯрдкреБрдЯ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ, рдЖрдкрдХреЛ рдиреЗрдЯрд╡рд░реНрдХ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд╡реИрдХрд▓реНрдкрд┐рдХ рддрд░реАрдХреЛрдВ (рд╣рдорд╛рд░реЗ рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЗ рд▓рд┐рдП рдПрдбреЗрдкреНрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдПрдХ рддрд░реАрдХрд╛ рд╣реИ рдЖрдЙрдЯрдкреБрдЯ рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП, рдФрд░ рдЙрдиреНрд╣реЗрдВ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ 100% рдХрд╡рд░реЗрдЬ рд╣реИред рдЯреЗрд╕реНрдЯ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╣рд░ рдкрдВрдХреНрддрд┐ рдФрд░ рд╣рд░ рд╕рдВрднрд╛рд╡рд┐рдд рддреНрд░реБрдЯрд┐ рдХреЗ рд▓рд┐рдП рдЖрд╡реЗрджрди рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреА рдЬрд╛рдВрдЪ рдХрд░рддреЗ рд╣реИрдВред


100% рдХрд╡рд░реЗрдЬ рдХреЗ рд▓рд┐рдП рд╕рдбрд╝рдХ рдкрд░ рдкреНрд░рддреНрдпреЗрдХ рдХрджрдо рдиреЗ рдЖрд╡реЗрджрди рдХреА рдкреНрд░рддрд┐рд░реВрдкрдХрддрд╛, рд╕реНрдерд┐рд░рддрд╛ рдФрд░ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдпрддрд╛ рдХреЛ рдмрдврд╝рд╛рдпрд╛, рдЗрд╕рд▓рд┐рдП рдЗрд╕ рддрдереНрдп рдХреЗ рд╕рд╛рде рдХреБрдЫ рднреА рдЧрд▓рдд рдирд╣реАрдВ рд╣реИ рдХрд┐ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдиреЗ рдкреИрдХреЗрдЬ рдХреА рд╕рдВрд░рдЪрдирд╛ рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдпрд╛ред


рдХрд┐рд╕реА рднреА рдХреЛрдб рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдПрдХ рдЧреБрдгрд╡рддреНрддрд╛ рд╣реИ рдЬреЛ рд╣рд╡рд╛ рд╕реЗ рдкреНрд░рдХрдЯ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред рдЬрдм рдбреЗрд╡рд▓рдкрд░ рдкрд░реНрдпрд╛рдкреНрдд рд░реВрдк рд╕реЗ рдЙрдкрдпреБрдХреНрдд рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдореЗрдВ рдкреИрдЯрд░реНрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдХрд╕реНрдЯрдо рдФрд░ рдореЙрдбреНрдпреВрд▓рд░ рдХреЛрдб рд▓рд┐рдЦрддрд╛ рд╣реИ рддреЛ рдкрд░реАрдХреНрд╖рдгрд╢реАрд▓рддрд╛ рджрд┐рдЦрд╛рдИ рджреЗрддреА рд╣реИред рдореБрдЦреНрдп рдХрд╛рд░реНрдп рдпрд╣ рдерд╛ рдХрд┐ рд░рд┐рдлреИрдХреНрдЯрд░рд┐рдВрдЧ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХрд░рддреЗ рд╕рдордп рд╕реЛрдЪ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рджрд┐рдЦрд╛рдпрд╛ рдЬрд╛рдПред рдЗрд╕реА рддрд░рд╣ рдХреА рд╕реЛрдЪ рдХрд┐рд╕реА рднреА рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдФрд░ рд▓рд╛рдЗрдмреНрд░реЗрд░реА, рд╕рд╛рде рд╣реА рдЕрдиреНрдп рднрд╛рд╖рд╛рдУрдВ рддрдХ рдмрдврд╝ рд╕рдХрддреА рд╣реИред

Source: https://habr.com/ru/post/hi452702/


All Articles