Архив рубрики: Golang

Go lang IDE environment

В процессе изучения языка программирования Go я перепробывал несколько IDE: это и столь уважаемый старичок vim, это и ужасный goclipse (GoLang плагин для Eclipse) и конечно же столь любимый GoLang плагин для intellij. С последним одна незадача: плагин доступен только для платной версии intellij.

Казалось бы самое время всгрустнуть, но как говорится «живость ума …» — для свободного скачивания доступна IDE под немудреннам названием go-ide. По сути это всё та же (бесплатная!) intellij, но с уже со встроенной поддержкой Go. Пользуемся и наслаждаемся 🙂

Отмечено

Язык программирования Go: а где же Generics ?!

Решил тут я недавича совместить полензное-с-полезным, то есть продолжить изучение Go и углубить свои познания в алгоритмах.  Как показали неудачно пройденные интервью, алгоритмы надо знать и не мучаться в поисках ответов на вопросы «что такое o-маленькое и что такое О-большое».  Все мои потуги вылились в проект golang-algoпервоначальная идея проекта — это реализация алгоритмов, описанных в курсе Introduction to Algorithms (SMA 5503)Приглашаю всех желающих присоединиться — не хватает общения с умными и образованными людьми 🙂

Ну а теперь к сути проблемы: мой первый insertsort алгоритм был написан для коллекций целочисленных чисел, иначе говоря int. На практике хотелось бы иметь generic алгоритмы,  для коллекций любых элементов, реализующих нечто вроде метода equals, на подобе того, что мы имеем в java.util.Collections:

public static <T> void sort(List<T> list, Comparator<? super T> c)

Читать далее

Отмечено

Язык программирования Go: что такое методы

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

 
func test() {
}

А как же обстоят дела с методами класса ? Тут все несколько хитрее: во-первых в Go не существует классов в привычном для С++ или Java виде. Вместо классов Go предлагает всего лишь структуру иначе говоря набор полей (привет plain C)

type myType struct{
fld1 string
fld2 int32
}

 

А под методом класса (пардон структуры) выступает «сообщение«, которое может быть послано инстансу определенного типа (рессивер), пример:

func (t myType) test( ) {                                 (1)
}
func (t *myType) test() {                                 (2)
}

И в первом и во втором случае в скобках между func и названием метода мы указываем тип рессивера которому будет послано сообщение, в данном случае это будет тип myType. Важно понимать, что как первое сообщение, так и второе может быть послано как указателю типа myType,  так и value значению типа myType. Отличие первой сигнатуры от второй заключается в том, что в первом случае будет передаваться полная копия перменной, во втором оригинал. Снова поясню на примере:

package main
import "fmt"
type myType struct {

 fld1 string
}
func (t *myType) test() {
 t.fld1 = t.fld1 + " updated"
}
func main() {

 t1 := myType{"t1"}
 t2 := new(myType)
 t2.fld1 = "t2"

 t1.test()
 t2.test()

 fmt.Println(t1.fld1)
 fmt.Println(t2.fld1)
}

Результат выглядит как

t1 updated
t2 updated

Замечу, что переменая t1 это переменная value типа, а переменная t2 это указатель. В случае если бы сигнатура метода выглядела бы как

func (t myType) test() {
 t.fld1 = t.fld1 + " updated"
}

То результат выполнения программы был бы:

t1
t2

Так как в метод test передаются  полные копии (!) value и pointer объектов.

Как мы видим столь привычный нам по C++ полиморфизм в Go просто не работает, указатели используются только для «быстрой» передачи структур большого размера  и речи о таблице(ах) виртуальных функциц вообще не идет. К этому стоит привыкнуть 🙂

Интересно а как решается классическая задача любого собеседования «у вас есть коллекция геометрических фигур; какую иерархию классов Вы бы предложили чтобы реализовать отрисовку фигур, принадлежащих коллекции ?!». Наверное надо использовать interface, но это вопрос уже следующей статьи 🙂

Отмечено

Язык программирования Go: используем прокси в HTTP соединении

В языке Go, впрочем как наверное и в большинстве современных языках программирования, задача написания HTTP клиента тривиальна — достаточно воспользоваться уже готовой библиотекой. В Go таковой является пакет net/htpp (ктсати в Java я пользуюс Apache HTTP client). Вот как примерно выглядит код по чтению HTML старницы:

resp, err := http.Get("http://example.com/")
if err != nil {
	// handle error
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)


Всё бы хорошо до тех пор, пока нет необходимости ходить через прокси (вдруг вы эксперементируете с Go в обеденный перерыв на рабочем месте 😉 ). Но и тут все довольно просто,http.DefaultTransport , являющийся траснпортом «по умолчанию» для пакета http читает конфигурацию прокси из переменной окружения «HTTP_PROXY» и нам необходимо добавить всего лишь одну строчку кода:

os.Setenv("HTTP_PROXY", "host:port")
resp, err := http.Get("http://example.com/")
if err != nil {
	// handle error
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)

 Вуаля 🙂
Отмечено

Язык программирования Go: вопросы установки

Сегодня рассмотрим процесс установки Go на примере Linux Ubuntu. Существуют два, а точнее даже три способа устновки дистрибутива:

  • Первый описан на странице «Getting Started» проекта Golang. На мой взгляд самый муторный и малоинтересный
  • Второй способ (более лёгкий), это уставнока всё того же дистрибутива но уже из репозитория Ubuntu

sudo apt-get install golang-go

Независимо от того какой путь вы выбрали, у вас на рабочей станции будет установлен достаточно «древне-скучная-а-потому-и-неинтерсная» версия языка Go. Мой вам совет используйте nightly build. Процесс установки не так , чтобы уже сложен, посудите сами:

  • Скачиваем архив
  • Распаковываем его содержимое в папку /opt
  • Правим ~/.profile

export GOROOT=/opt/go
export PATH=»$GOROOT/bin:$PATH»

  • Перегружаем профайл

source ~/.profile

Вуаля, немного командной строки и у нас «свежая» версия Go с новейшим компилятором и без всяких там (8g, 8l и прочей чепухи).

p.s. Еще один способ установки т.н. Go nightly builds, предложен Алексеем Харченко (за что ему собственно отдельное спасибо). Установку, а что главное и автоматическое обновление nightly build можно реализовать также с помощью репозитария Ubuntu:

Within the PPA, the following packages are available:

  • golang-stable — Updated with the current stable release.
  • golang-weekly — Updated with the current weekly release.
  • golang-tip — Updated daily with the latest changes in the repository tip.

To install the packages, simply paste the following lines in a terminal:

sudo add-apt-repository ppa:gophers/go
sudo apt-get update
sudo apt-get install golang-stable # Or golang-weekly, or golang-tip

Стоит также отметить, что на моент написания этой статьи пакет golang-stable содержал довольно старую версию Go, так что, все golang-weekly — это мой выбор.

Отмечено

Язык программирования Go: тип данных func

Сегодня расскажу об одной интересной, покрайней мере для меня, особенности языка Go как тип даных func.  Данный тип во многом похож на те же указатели на функции в С++.  И так начнем с примера:

package main
import "fmt"
type MyFunc func (arg string)
/** method of MyFunc type*/
func myFunc1(arg string){
 fmt.Println("myFunc1: " + arg)
}
/** method to test MyFunc type*/
func test(f MyFunc){
 /** simply call MyFunc method*/
 f("test")
}
func main() {
 /** declare anonymous method*/
 f := func (arg string){
 fmt.Print("Anonymous: " + arg)
 }

 /** test*/
 test(myFunc1)
 /** test anonymous*/
 test(f)
}
Result:
myFunc1: test
Anonymous: test

Читать далее

Отмечено

Язык программирования Go: File vs FileReader

Многие из нас сталкивались с задачей чтения даных из файла, задача сама по себе тривиальна, но её реализация, это как модно сегодня говорить «печалька». Возьмем хотябы Java: для этих целей Java SE предоставляет целый набор классов и нтерфейсов java.io.Reader, java.io.File, java.io.FileReader, java.io.BufferedReader.  В самом плохом сценарии вызов некоего метода:

void parseData(Reader reader)
{
}

Оборачивается в:

obj.parseData(new BufferedReader(new FileReader(new File("file.txt"))))

«Печалька» и скукотища 😦

Изучая Go я также решил протестировать его на задачу «чтения из файла»,  тип File я нашел довольно быстро (хотя странно что он распологается в пакете os, а не io как я ожидал).  Затем настал черед FileReader’a.  Тут уж пришлось попотеть, «облазив» практически все пакеты, я так и не нашел такой тип — небольшой ступор. И только прочитав про концепцию интерфейсов в Go я понял, что тип File уже сам реализует интефейс Reader (!wow очень элегантно!). Код чтения данных уже выглядит иначе:

package main
import (
"os"
"io"
}

func readData(io.Reader r){
}
func main(){
/** открываем файл*/
r,_ := os.Open("test.html")
/** читаем данные*/
readData(r)
}

Несомненно и в Go существуют отпимизации в виде bytes.BufferedReader, оборачивающие оригинальный reader, но это уже частности.

Кстати насчёт интерфейсов, как я понимаю в Go интерфейсы это всего лишь логическая группировка методов. То есть можно объявить интерфейс, как в случае с io.Reader

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

Но сами интерфейсы явно не наследуются, любой тип реализовавший метод

Read(p []byte) (n int, err os.Error)

уже считается унаследовавшим-и-реализовавшим интерфейс io.Reader, собственно как это произошло с типом os.File

Отмечено

Язык программирования Go: первые впечатления

Как всегда не сижу на месте, ищу приключения на свой головной мозг :-). Вокруг творится столько интересного и «вкусного», что пройти мимо ну просто нет никакой возможности. Одно из последних «блюд» это язык программирования Go.

Go изобрела всем изветсная «компания добра» Google и как сами утверждают отцы-основатели, Go является одним из инструментов создания внутрекорпаративных систем. Его выделяет простота использования и огроменные возможности (про последнее врать не буду, сам во всем этом новичек). Простота и даже некая элегантность действительно присуща этому языку. Вот лишь некоторые конструкции вызвавшие мое восхищение:

Всем знаком foreach в Java, но как часто нам кроме самого элемента, надо получить еще его индекс и вот код выливается в нечто:

String[] values = new String[] {"value1", "value2"};
int i = 0;
foreach(String s : values)
{
 i++;
}

Как же всё это выглядит в красавце Go

 values := []string{"value1", "value2"}
 for i, s :=range values {
 fmt.Println(i, s)
 }

Как вы сами заметили в одной строке мы получаем доступ как элементу, так и к индексу массива (wow!). «Мелочь» — скажите вы, «Элегантность» — парирую я !

Ну и само собой нектороые замечания и так по порядку:

  • Открывающая скобка «{» на той же строке что и оператор (метод, тип и т.д.) это не особенности форматирования кода, а как я понимаю требования языка. Если вы перенесете скобку на следующую строку, то получите ошибку компиляции.
  • Жёсткое требование языка: если переменная объявлена, то она должна быть обязательно использована (!wow — круто). То есть вот такая конструкция уже не скомпилируется (переменная i нигде не используется):
values := []string{"value1", "value2"}
 for i, s :=range values {
fmt.Println(s)
 }
  • Решается эта проблема просто, одно из значений возвращаемых методом range, да-да в Go методы могут возвращать более одного знаяения, можно «игнорировать» с помощью «_», то есть правильный код должен выглядеть так
values := []string{"value1", "value2"}
 for _, s :=range values {
fmt.Println(s)
 }
  • «Играть» с Go лучше в Linux, под Windows существует только эксперементальная сборка
  • Ну и для любителей Eclipse существует plugin. «Подстветка синтаксиса» — это всё, что он умеет делать хорошо 🙂
Отмечено