From 406e001add35a3496de3d87bbabd6ca84f95a6fb Mon Sep 17 00:00:00 2001 From: Bora Kaplan Date: Mon, 29 Aug 2016 19:19:29 +0300 Subject: [PATCH 1/4] Translating 02.3 to Turkish Not complete --- tr/02.3.md | 516 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 516 insertions(+) create mode 100644 tr/02.3.md diff --git a/tr/02.3.md b/tr/02.3.md new file mode 100644 index 00000000..54815068 --- /dev/null +++ b/tr/02.3.md @@ -0,0 +1,516 @@ +# 2.3 Kontrol ifadeleri ve fonksiyonlar + +Bu bölümde, Go da kontrol ifadeleri ve fonksiyon işlemleri hakkında konuşacağız. + +## Kontrol ifadesi + +Akış kontrolü programcılıkta en büyük icattır. Onun sayesinde, basit kontrol ifadeleri kullanarak daha karmaşık lojik ifadeler temsil edilebilir. Akış kontrolünü üç kategoriye ayırabiliriz: şartlı, döngü kontrollü ve şartsız çıkış. + +### if + +'if' kelimesi büyük ihtimalle programlarında en sık geçen kelimedir. Eğer şartlar sağlanırsa birşeyler yapar, sağlanmazsa başka şeyler yapar. + +'if' şartları için Go da paranteze gerek yoktur. + + if x > 10 { + fmt.Println("x is greater than 10") + } else { + fmt.Println("x is less than or equal to 10") + } + +Go da çok işe yarar bir 'if' kullanımı, şart ifadesinden önce değişken tanımlama yapmaktır. Bu değişkenin kapsamı sadece 'if' blok alanı içerisinde geçerlidir. + + // x'i tanımla, ve 10 dan büyük olup olmadığını kontrol et + if x := computedValue(); x > 10 { + fmt.Println("x is greater than 10") + } else { + fmt.Println("x is less than 10") + } + + // Bu satır derlenemez + fmt.Println(x) + +Birden fazla şart için if-else kullanın. + + if integer == 3 { + fmt.Println("The integer is equal to 3") + } else if integer < 3 { + fmt.Println("The integer is less than 3") + } else { + fmt.Println("The integer is greater than 3") + } + +### goto + +Go has a `goto` keyword, but be careful when you use it. `goto` reroutes the control flow to a previously defined `label` within the body of same code block. + + func myFunc() { + i := 0 + Here: // label ends with ":" + fmt.Println(i) + i++ + goto Here // jump to label "Here" + } + +The label name is case sensitive. + +### for + +`for` is the most powerful control logic in Go. It can read data in loops and iterative operations, just like `while`. + + for expression1; expression2; expression3 { + //... + } + +`expression1`, `expression2` and `expression3` are all expressions, where `expression1` and `expression3` are variable definitions or return values from functions, and `expression2` is a conditional statement. `expression1` will be executed once before looping, and `expression3` will be executed after each loop. + +Examples are more useful than words. + + package main + import "fmt" + + func main(){ + sum := 0; + for index:=0; index < 10 ; index++ { + sum += index + } + fmt.Println("sum is equal to ", sum) + } + // Print:sum is equal to 45 + +Sometimes we need multiple assignments, but Go doesn't have the `,` operator, so we use parallel assignment like `i, j = i + 1, j - 1`. + +We can omit `expression1` and `expression3` if they are not necessary. + + sum := 1 + for ; sum < 1000; { + sum += sum + } + +Omit `;` as well. Feel familiar? Yes, it's identical to `while`. + + sum := 1 + for sum < 1000 { + sum += sum + } + +There are two important operations in loops which are `break` and `continue`. `break` jumps out of the loop, and `continue` skips the current loop and starts the next one. If you have nested loops, use `break` along with labels. + + for index := 10; index>0; index-- { + if index == 5{ + break // or continue + } + fmt.Println(index) + } + // break prints 10、9、8、7、6 + // continue prints 10、9、8、7、6、4、3、2、1 + +`for` can read data from `slice` and `map` when it is used together with `range`. + + for k,v:=range map { + fmt.Println("map's key:",k) + fmt.Println("map's val:",v) + } + +Because Go supports multi-value returns and gives compile errors when you don't use values that were defined, you may want to use `_` to discard certain return values. + + for _, v := range map{ + fmt.Println("map's val:", v) + } + +### switch + +Sometimes you may find that you are using too many `if-else` statements to implement some logic, which may make it difficult to read and maintain in the future. This is the perfect time to use the `switch` statement to solve this problem. + + switch sExpr { + case expr1: + some instructions + case expr2: + some other instructions + case expr3: + some other instructions + default: + other code + } + +The type of `sExpr`, `expr1`, `expr2`, and `expr3` must be the same. `switch` is very flexible. Conditions don't have to be constants and it executes from top to bottom until it matches conditions. If there is no statement after the keyword `switch`, then it matches `true`. + + i := 10 + switch i { + case 1: + fmt.Println("i is equal to 1") + case 2, 3, 4: + fmt.Println("i is equal to 2, 3 or 4") + case 10: + fmt.Println("i is equal to 10") + default: + fmt.Println("All I know is that i is an integer") + } + +In the fifth line, we put many values in one `case`, and we don't need to add the `break` keyword at the end of `case`'s body. It will jump out of the switch body once it matched any case. If you want to continue to matching more cases, you need to use the`fallthrough` statement. + + integer := 6 + switch integer { + case 4: + fmt.Println("integer <= 4") + fallthrough + case 5: + fmt.Println("integer <= 5") + fallthrough + case 6: + fmt.Println("integer <= 6") + fallthrough + case 7: + fmt.Println("integer <= 7") + fallthrough + case 8: + fmt.Println("integer <= 8") + fallthrough + default: + fmt.Println("default case") + } + +This program prints the following information. + + integer <= 6 + integer <= 7 + integer <= 8 + default case + +## Functions + +Use the `func` keyword to define a function. + + func funcName(input1 type1, input2 type2) (output1 type1, output2 type2) { + // function body + // multi-value return + return value1, value2 + } + +We can extrapolate the following information from the example above. + +- Use keyword `func` to define a function `funcName`. +- Functions have zero, one or more than one arguments. The argument type comes after the argument name and arguments are separated by `,`. +- Functions can return multiple values. +- There are two return values named `output1` and `output2`, you can omit their names and use their type only. +- If there is only one return value and you omitted the name, you don't need brackets for the return values. +- If the function doesn't have return values, you can omit the return parameters altogether. +- If the function has return values, you have to use the `return` statement somewhere in the body of the function. + +Let's see one practical example. (calculate maximum value) + + package main + import "fmt" + + // return greater value between a and b + func max(a, b int) int { + if a > b { + return a + } + return b + } + + func main() { + x := 3 + y := 4 + z := 5 + + max_xy := max(x, y) // call function max(x, y) + max_xz := max(x, z) // call function max(x, z) + + fmt.Printf("max(%d, %d) = %d\n", x, y, max_xy) + fmt.Printf("max(%d, %d) = %d\n", x, z, max_xz) + fmt.Printf("max(%d, %d) = %d\n", y, z, max(y,z)) // call function here + } + +In the above example, there are two arguments in the function `max`, their types are both `int` so the first type can be omitted. For instance, `a, b int` instead of `a int, b int`. The same rules apply for additional arguments. Notice here that `max` only has one return value, so we only need to write the type of its return value -this is the short form of writing it. + +### Multi-value return + +One thing that Go is better at than C is that it supports multi-value returns. + +We'll use the following example here. + + package main + import "fmt" + + // return results of A + B and A * B + func SumAndProduct(A, B int) (int, int) { + return A+B, A*B + } + + func main() { + x := 3 + y := 4 + + xPLUSy, xTIMESy := SumAndProduct(x, y) + + fmt.Printf("%d + %d = %d\n", x, y, xPLUSy) + fmt.Printf("%d * %d = %d\n", x, y, xTIMESy) + } + +The above example returns two values without names -you have the option of naming them also. If we named the return values, we would just need to use `return` to return the values since they are initialized in the function automatically. Notice that if your functions are going to be used outside of the package, which means your function names start with a capital letter, you'd better write complete statements for `return`; it makes your code more readable. + + func SumAndProduct(A, B int) (add int, multiplied int) { + add = A+B + multiplied = A*B + return + } + +### Variadic functions + +Go supports functions with a variable number of arguments. These functions are called "variadic", which means the function allows an uncertain numbers of arguments. + + func myfunc(arg ...int) {} + +`arg …int` tells Go that this is a function that has variable arguments. Notice that these arguments are type `int`. In the body of function, the `arg` becomes a `slice` of `int`. + + for _, n := range arg { + fmt.Printf("And the number is: %d\n", n) + } + +### Pass by value and pointers + +When we pass an argument to the function that was called, that function actually gets the copy of our variables so any change will not affect to the original variable. + +Let's see one example in order to prove what i'm saying. + + package main + import "fmt" + + // simple function to add 1 to a + func add1(a int) int { + a = a+1 // we change value of a + return a // return new value of a + } + + func main() { + x := 3 + + fmt.Println("x = ", x) // should print "x = 3" + + x1 := add1(x) // call add1(x) + + fmt.Println("x+1 = ", x1) // should print "x+1 = 4" + fmt.Println("x = ", x) // should print "x = 3" + } + +Can you see that? Even though we called `add1` with `x`, the origin value of `x` doesn't change. + +The reason is very simple: when we called `add1`, we gave a copy of `x` to it, not the `x` itself. + +Now you may ask how I can pass the real `x` to the function. + +We need use pointers here. We know variables are stored in memory and they have some memory addresses. So, if we want to change the value of a variable, we must change its memory address. Therefore the function `add1` has to know the memory address of `x` in order to change its value. Here we pass `&x` to the function, and change the argument's type to the pointer type `*int`. Be aware that we pass a copy of the pointer, not copy of value. + + package main + import "fmt" + + // simple function to add 1 to a + func add1(a *int) int { + *a = *a+1 // we changed value of a + return *a // return new value of a + } + + func main() { + x := 3 + + fmt.Println("x = ", x) // should print "x = 3" + + x1 := add1(&x) // call add1(&x) pass memory address of x + + fmt.Println("x+1 = ", x1) // should print "x+1 = 4" + fmt.Println("x = ", x) // should print "x = 4" + } + +Now we can change the value of `x` in the functions. Why do we use pointers? What are the advantages? + +- Allows us to use more functions to operate on one variable. +- Low cost by passing memory addresses (8 bytes), copy is not an efficient way, both in terms of time and space, to pass variables. +- `string`, `slice` and `map` are reference types, so they use pointers when passing to functions by default. (Attention: If you need to change the length of `slice`, you have to pass pointers explicitly) + +### defer + +Go has a well designed keyword called `defer`. You can have many `defer` statements in one function; they will execute in reverse order when the program executes to the end of functions. In the case where the program opens some resource files, these files would have to be closed before the function can return with errors. Let's see some examples. + + func ReadWrite() bool { + file.Open("file") + // Do some work + if failureX { + file.Close() + return false + } + + if failureY { + file.Close() + return false + } + + file.Close() + return true + } + +We saw some code being repeated several times. `defer` solves this problem very well. It doesn't only help you to write clean code but also makes your code more readable. + + func ReadWrite() bool { + file.Open("file") + defer file.Close() + if failureX { + return false + } + if failureY { + return false + } + return true + } + +If there are more than one `defer`s, they will execute by reverse order. The following example will print `4 3 2 1 0`. + + for i := 0; i < 5; i++ { + defer fmt.Printf("%d ", i) + } + +### Functions as values and types + +Functions are also variables in Go, we can use `type` to define them. Functions that have the same signature can be seen as the same type. + + type typeName func(input1 inputType1 , input2 inputType2 [, ...]) (result1 resultType1 [, ...]) + +What's the advantage of this feature? The answer is that it allows us to pass functions as values. + + package main + import "fmt" + + type testInt func(int) bool // define a function type of variable + + func isOdd(integer int) bool { + if integer%2 == 0 { + return false + } + return true + } + + func isEven(integer int) bool { + if integer%2 == 0 { + return true + } + return false + } + + // pass the function `f` as an argument to another function + + func filter(slice []int, f testInt) []int { + var result []int + for _, value := range slice { + if f(value) { + result = append(result, value) + } + } + return result + } + + func main(){ + slice := []int {1, 2, 3, 4, 5, 7} + fmt.Println("slice = ", slice) + odd := filter(slice, isOdd) // use function as values + fmt.Println("Odd elements of slice are: ", odd) + even := filter(slice, isEven) + fmt.Println("Even elements of slice are: ", even) + } + +It's very useful when we use interfaces. As you can see `testInt` is a variable that has a function as type and the returned values and arguments of `filter` are the same as those of `testInt`. Therefore, we can have complex logic in our programs, while maintaining flexibility in our code. + +### Panic and Recover + +Go doesn't have `try-catch` structure like Java does. Instead of throwing exceptions, Go uses `panic` and `recover` to deal with errors. However, you shouldn't use `panic` very much, although it's powerful. + +`Panic` is a built-in function to break the normal flow of programs and get into panic status. When a function `F` calls `panic`, `F` will not continue executing but its `defer` functions will continue to execute. Then `F` goes back to the break point which caused the panic status. The program will not terminate until all of these functions return with panic to the first level of that `goroutine`. `panic` can be produced by calling `panic` in the program, and some errors also cause `panic` like array access out of bounds errors. + +`Recover` is a built-in function to recover `goroutine`s from panic status. Calling `recover` in `defer` functions is useful because normal functions will not be executed when the program is in the panic status. It catches `panic` values if the program is in the panic status, and it gets `nil` if the program is not in panic status. + +The following example shows how to use `panic`. + + var user = os.Getenv("USER") + + func init() { + if user == "" { + panic("no value for $USER") + } + } + +The following example shows how to check `panic`. + + func throwsPanic(f func()) (b bool) { + defer func() { + if x := recover(); x != nil { + b = true + } + }() + f() // if f causes panic, it will recover + return + } + +### `main` function and `init` function + +Go has two retentions which are called `main` and `init`, where `init` can be used in all packages and `main` can only be used in the `main` package. These two functions are not able to have arguments or return values. Even though we can write many `init` functions in one package, I strongly recommend writing only one `init` function for each package. + +Go programs will call `init()` and `main()` automatically, so you don't need to call them by yourself. For every package, the `init` function is optional, but `package main` has one and only one `main` function. + +Programs initialize and begin execution from the `main` package. If the `main` package imports other packages, they will be imported in the compile time. If one package is imported many times, it will be only compiled once. After importing packages, programs will initialize the constants and variables within the imported packages, then execute the `init` function if it exists, and so on. After all the other packages are initialized, programs will initialize constants and variables in the `main` package, then execute the `init` function inside the package if it exists. The following figure shows the process. + +![](images/2.3.init.png?raw=true) + +Figure 2.6 Flow of programs initialization in Go + +### import + +We use `import` very often in Go programs as follows. + + import( + "fmt" + ) + +Then we use functions in that package as follows. + + fmt.Println("hello world") + +`fmt` is from Go standard library, it is located within $GOROOT/pkg. Go supports third-party packages in two ways. + +1. Relative path + import "./model" // load package in the same directory, I don't recommend this way. +2. Absolute path + import "shorturl/model" // load package in path "$GOPATH/pkg/shorturl/model" + +There are some special operators when we import packages, and beginners are always confused by these operators. + +1. Dot operator. + Sometime we see people use following way to import packages. + + import( + . "fmt" + ) + + The dot operator means you can omit the package name when you call functions inside of that package. Now `fmt.Printf("Hello world")` becomes to `Printf("Hello world")`. +2. Alias operation. + It changes the name of the package that we imported when we call functions that belong to that package. + + import( + f "fmt" + ) + + Now `fmt.Printf("Hello world")` becomes to `f.Printf("Hello world")`. +3. `_` operator. + This is the operator that is difficult to understand without someone explaining it to you. + + import ( + "database/sql" + _ "github.com/ziutek/mymysql/godrv" + ) + + The `_` operator actually means we just want to import that package and execute its `init` function, and we are not sure if want to use the functions belonging to that package. + +## Links + +- [Directory](preface.md) +- Previous section: [Go foundation](02.2.md) +- Next section: [struct](02.4.md) From 357d0aaad1fa47088e392717209cc7eb6a4f29df Mon Sep 17 00:00:00 2001 From: Bora Kaplan Date: Mon, 29 Aug 2016 22:10:15 +0300 Subject: [PATCH 2/4] Halfway done on 02.3.md in tr --- tr/02.3.md | 73 +++++++++++++++++++++++++++--------------------------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/tr/02.3.md b/tr/02.3.md index 54815068..4b18cf2e 100644 --- a/tr/02.3.md +++ b/tr/02.3.md @@ -8,9 +8,9 @@ Akış kontrolü programcılıkta en büyük icattır. Onun sayesinde, basit kon ### if -'if' kelimesi büyük ihtimalle programlarında en sık geçen kelimedir. Eğer şartlar sağlanırsa birşeyler yapar, sağlanmazsa başka şeyler yapar. +`if` kelimesi büyük ihtimalle programlarında en sık geçen kelimedir. Eğer şartlar sağlanırsa birşeyler yapar, sağlanmazsa başka şeyler yapar. -'if' şartları için Go da paranteze gerek yoktur. +`if` şartları için Go da paranteze gerek yoktur. if x > 10 { fmt.Println("x is greater than 10") @@ -18,7 +18,7 @@ Akış kontrolü programcılıkta en büyük icattır. Onun sayesinde, basit kon fmt.Println("x is less than or equal to 10") } -Go da çok işe yarar bir 'if' kullanımı, şart ifadesinden önce değişken tanımlama yapmaktır. Bu değişkenin kapsamı sadece 'if' blok alanı içerisinde geçerlidir. +Go da çok işe yarar bir `if` kullanımı, şart ifadesinden önce değişken tanımlama yapmaktır. Bu değişkenin kapsamı sadece `if` blok alanı içerisinde geçerlidir. // x'i tanımla, ve 10 dan büyük olup olmadığını kontrol et if x := computedValue(); x > 10 { @@ -30,7 +30,7 @@ Go da çok işe yarar bir 'if' kullanımı, şart ifadesinden önce değişken t // Bu satır derlenemez fmt.Println(x) -Birden fazla şart için if-else kullanın. +Birden fazla şart için `if-else` kullanın. if integer == 3 { fmt.Println("The integer is equal to 3") @@ -42,7 +42,7 @@ Birden fazla şart için if-else kullanın. ### goto -Go has a `goto` keyword, but be careful when you use it. `goto` reroutes the control flow to a previously defined `label` within the body of same code block. +Go da `goto` terimi mevcuttur fakat kullanırken dikkatli olun. `goto` programın kontrol akışını önceden belirlenmiş aynı gövde içindeki bir `label` a yönlendirir. func myFunc() { i := 0 @@ -52,19 +52,19 @@ Go has a `goto` keyword, but be careful when you use it. `goto` reroutes the con goto Here // jump to label "Here" } -The label name is case sensitive. +Label'ın adı büyük-küçük harfe duyarlıdır. ### for -`for` is the most powerful control logic in Go. It can read data in loops and iterative operations, just like `while`. +`for` Go da bulunan en güçlü kontrol lojiğidir. Datayı döngüsel olarak ve tekrarlı işlemlerle okuyabilir, `while` döngüsü gibi. for expression1; expression2; expression3 { //... } - -`expression1`, `expression2` and `expression3` are all expressions, where `expression1` and `expression3` are variable definitions or return values from functions, and `expression2` is a conditional statement. `expression1` will be executed once before looping, and `expression3` will be executed after each loop. -Examples are more useful than words. +`expression1`, `expression2` ve `expression3` birer ifade olmak üzere, `expression1` ve `expression3` değişken tanımlama veya bir fonksiyondan dönen return olabilirken, `expression2` ise kontrol ifadesidir. `expression1` ifadesi döngüye girmeden önce bir kere işlenecektir. `expression3` ise her döngü sonunda işlenir. + +Örnekler düz yazıdan daha yararlı olacaktır. package main import "fmt" @@ -78,23 +78,23 @@ Examples are more useful than words. } // Print:sum is equal to 45 -Sometimes we need multiple assignments, but Go doesn't have the `,` operator, so we use parallel assignment like `i, j = i + 1, j - 1`. +Bazen birden fazla atama yapmak gerekir fakat Go bunun için kullanılacak bir `,` operatörü yoktur. Biz de `i, j = i + 1, j - 1` gibi paralel atamalar yaparız. -We can omit `expression1` and `expression3` if they are not necessary. +İhtiyacımız yoksa `expression1` ve `expression1` ifadelerini çıkarabiliriz. sum := 1 for ; sum < 1000; { sum += sum } - -Omit `;` as well. Feel familiar? Yes, it's identical to `while`. + +Hatta `;` bile çıkarılabilir. Tanıdık geldi mi? Evet, tamamen `while` gibi oldu. sum := 1 for sum < 1000 { sum += sum } - -There are two important operations in loops which are `break` and `continue`. `break` jumps out of the loop, and `continue` skips the current loop and starts the next one. If you have nested loops, use `break` along with labels. + +Döngülerde `break` ve `continue` adında iki önemli işlem vardır. `break` döngüden çıkartır ve `continue` o anki tekrarı atlar ve sonraki tekrara geçer. Eğer birden fazla iç içe döngüleriniz varsa `break` ile labelları kullabilirsiniz. for index := 10; index>0; index-- { if index == 5{ @@ -104,15 +104,15 @@ There are two important operations in loops which are `break` and `continue`. `b } // break prints 10、9、8、7、6 // continue prints 10、9、8、7、6、4、3、2、1 - -`for` can read data from `slice` and `map` when it is used together with `range`. + +`for` döngüsü `range` kullanıldığında `slice` ve `map` de bulunan datayı okuyabilir. for k,v:=range map { fmt.Println("map's key:",k) fmt.Println("map's val:",v) } - -Because Go supports multi-value returns and gives compile errors when you don't use values that were defined, you may want to use `_` to discard certain return values. + +Go da birden fazla değer return yapılabildiği ve kullanılmayan bir değişken olduğunda derleyici hata verdiği için, kullanmak istemediğiniz değişkenler için `_` kullanabilirsiniz. for _, v := range map{ fmt.Println("map's val:", v) @@ -120,7 +120,7 @@ Because Go supports multi-value returns and gives compile errors when you don't ### switch -Sometimes you may find that you are using too many `if-else` statements to implement some logic, which may make it difficult to read and maintain in the future. This is the perfect time to use the `switch` statement to solve this problem. +Bazı durumlarda çok fazla `if-else` kullandığınızı farkedebilirsiniz. Bu programı okumayı zorlaştırır ve gelecekte bakım yapmayı zorlaştırabilir. Bu durumda problemi çözmek için `switch` kullanmak mükemmeldir. switch sExpr { case expr1: @@ -132,8 +132,8 @@ Sometimes you may find that you are using too many `if-else` statements to imple default: other code } - -The type of `sExpr`, `expr1`, `expr2`, and `expr3` must be the same. `switch` is very flexible. Conditions don't have to be constants and it executes from top to bottom until it matches conditions. If there is no statement after the keyword `switch`, then it matches `true`. + +`sExpr`, `expr1`, `expr2`, ve `expr3` ifadelerinin türleri aynı olmalıdır. `switch` çok esnektir. Şartlar sabit olmak zorunda değildir ve şart sağlanana kadar yukarıdan aşağıya doğru çalışır. Eğer `switch` in ardından bir ifade gelmiyorsa `true` olarak görülür. i := 10 switch i { @@ -146,8 +146,8 @@ The type of `sExpr`, `expr1`, `expr2`, and `expr3` must be the same. `switch` is default: fmt.Println("All I know is that i is an integer") } - -In the fifth line, we put many values in one `case`, and we don't need to add the `break` keyword at the end of `case`'s body. It will jump out of the switch body once it matched any case. If you want to continue to matching more cases, you need to use the`fallthrough` statement. + +Beşinci satırdaki gibi `case` içinde birden fazla değer olabilir. `case` sonlarına `break` eklemeye gerek yoktur, şart sağlanıp işlem yapıldıktan sonra çıkacaktır. Eğer çıkmasını istemiyorsanız `fallthrough` ifadesini kullanarak bir sonraki şarta devam edebilirsiniz. integer := 6 switch integer { @@ -179,25 +179,24 @@ This program prints the following information. ## Functions -Use the `func` keyword to define a function. +`func` terimini kullanarak bir fonksiyon tanımlayın. func funcName(input1 type1, input2 type2) (output1 type1, output2 type2) { // function body // multi-value return return value1, value2 } - -We can extrapolate the following information from the example above. -- Use keyword `func` to define a function `funcName`. -- Functions have zero, one or more than one arguments. The argument type comes after the argument name and arguments are separated by `,`. -- Functions can return multiple values. -- There are two return values named `output1` and `output2`, you can omit their names and use their type only. -- If there is only one return value and you omitted the name, you don't need brackets for the return values. -- If the function doesn't have return values, you can omit the return parameters altogether. -- If the function has return values, you have to use the `return` statement somewhere in the body of the function. +Yukarıdaki örnekten tahmin edebileceğiniz üzere aşağıda açıklamaları bulunur. -Let's see one practical example. (calculate maximum value) +- `funcName` adlı foonksiyonu tanımlamak için `func` terimini kullanın. +- Fonksiyonlar sıfır veya daha fazla parametreye sahip olabilir. Parametrenin türü adından sonra gelir ve birden fazla parametre varsa `,` ile ayrılır. +- Fonksiyonlar birden fazla değer döndürebilirler. +- Bu örnekte `output1` ve `output2` adında iki değer döndürülmüş. Bunlara ad vermek zorunda değilsiniz, türünü yazmanız yeterli. +- Eğer sadece bir değer döndürecekseniz parantez olmadan yazmalısınız. +- Eğer en az bir değer döndürüyorsanız, fonksiyonun içinde istediğiniz yerde `return` terimini kullanmalısınız. + +Şimdi pratik bir örnek görelim. (Maksimum değerini hesaplama) package main import "fmt" @@ -223,7 +222,7 @@ Let's see one practical example. (calculate maximum value) fmt.Printf("max(%d, %d) = %d\n", y, z, max(y,z)) // call function here } -In the above example, there are two arguments in the function `max`, their types are both `int` so the first type can be omitted. For instance, `a, b int` instead of `a int, b int`. The same rules apply for additional arguments. Notice here that `max` only has one return value, so we only need to write the type of its return value -this is the short form of writing it. +Yukarıdaki örnek fonksiyon `max` da iki aynı tür parametre `int` olduğu için bir tane yazmak yeterli olur. Yani `a int, b int` yerine `a, b int` kullanılır. Birden fazla parametre için de aynı kural geçerlidir. Farkettiyseniz `max` fonksiyonu sadece bir değer döndürür ve zorunda olmadığımız için o değere bir isim vermedik, bu kısa halini kullandık. ### Multi-value return From f9ca488e1dfbad6a123377106e943ce167bb10c3 Mon Sep 17 00:00:00 2001 From: Bora Kaplan Date: Wed, 31 Aug 2016 01:34:43 +0300 Subject: [PATCH 3/4] Turkish 02.3.md almost done --- tr/02.3.md | 60 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/tr/02.3.md b/tr/02.3.md index 4b18cf2e..3e654abe 100644 --- a/tr/02.3.md +++ b/tr/02.3.md @@ -224,11 +224,11 @@ Yukarıdaki örnekten tahmin edebileceğiniz üzere aşağıda açıklamaları b Yukarıdaki örnek fonksiyon `max` da iki aynı tür parametre `int` olduğu için bir tane yazmak yeterli olur. Yani `a int, b int` yerine `a, b int` kullanılır. Birden fazla parametre için de aynı kural geçerlidir. Farkettiyseniz `max` fonksiyonu sadece bir değer döndürür ve zorunda olmadığımız için o değere bir isim vermedik, bu kısa halini kullandık. -### Multi-value return +### Çok değerli döndürme -One thing that Go is better at than C is that it supports multi-value returns. +Go'nun C'den iyi olduğu bir şey birden fazla değer döndürmeyi desteklemesidir. -We'll use the following example here. +Alttaki örnekte bunu kullanalım. package main import "fmt" @@ -248,7 +248,7 @@ We'll use the following example here. fmt.Printf("%d * %d = %d\n", x, y, xTIMESy) } -The above example returns two values without names -you have the option of naming them also. If we named the return values, we would just need to use `return` to return the values since they are initialized in the function automatically. Notice that if your functions are going to be used outside of the package, which means your function names start with a capital letter, you'd better write complete statements for `return`; it makes your code more readable. +Üstteki fonksiyon isimsiz iki değer döndürür -isterseniz isim verebilirsiniz. Eğer isimlendirseydik, `return` yazıp isimlerini yazmamız yeterdi. Çünkü fonksiyonun içinde tanımlılar. Şuna dikkat etmelisiniz ki eğer fonksiyonu başka bir pakette kullanacaksanız (fonksiyonun ilk harfi büyük harfle başlamalıdır) `return` yapacaklarınızı tam bir ifade olarak yazmanız daha iyi olacaktır. Kodu daha okunur hale getirir. func SumAndProduct(A, B int) (add int, multiplied int) { add = A+B @@ -256,23 +256,23 @@ The above example returns two values without names -you have the option of namin return } -### Variadic functions +### Variadic fonksiyonlar -Go supports functions with a variable number of arguments. These functions are called "variadic", which means the function allows an uncertain numbers of arguments. +Go birden fazla argüman alabilen fonksiyonları destekler. Bunlara variadic (belirsiz-değişen sayıda argüman alan) fonksiyon denir. func myfunc(arg ...int) {} -`arg …int` tells Go that this is a function that has variable arguments. Notice that these arguments are type `int`. In the body of function, the `arg` becomes a `slice` of `int`. +`arg …int` kısmı Go ya bu fonksiyonun değişen sayıda argüman aldığını söyler. Bu argümanların türü `int` dir. `arg` fonksiyonun gövdesinde `int` türünde bir `slice` olur. for _, n := range arg { fmt.Printf("And the number is: %d\n", n) } -### Pass by value and pointers +### Değer ile devretmek ve pointerlar -When we pass an argument to the function that was called, that function actually gets the copy of our variables so any change will not affect to the original variable. +Bir fonksiyon çağırıp ona argüman verdiğimizde o fonksiyon aslında değişkenin bir kopyasını alır. Dolayısı ile yapılan işlemler değişkende bir değişiklik yaratmaz. -Let's see one example in order to prove what i'm saying. +Bunun kanıtı olarak bir örnek görelim. package main import "fmt" @@ -293,14 +293,14 @@ Let's see one example in order to prove what i'm saying. fmt.Println("x+1 = ", x1) // should print "x+1 = 4" fmt.Println("x = ", x) // should print "x = 3" } - -Can you see that? Even though we called `add1` with `x`, the origin value of `x` doesn't change. -The reason is very simple: when we called `add1`, we gave a copy of `x` to it, not the `x` itself. +Gördünüz mü? `add1` fonksiyonuna `x` i gönderdiğimiz halde asıl değeri değişmedi. -Now you may ask how I can pass the real `x` to the function. +Sebebi basit: `add1` i çağırdığımızda ona `x` in bir kopyasını gönderdik `x` in kendisini değil. -We need use pointers here. We know variables are stored in memory and they have some memory addresses. So, if we want to change the value of a variable, we must change its memory address. Therefore the function `add1` has to know the memory address of `x` in order to change its value. Here we pass `&x` to the function, and change the argument's type to the pointer type `*int`. Be aware that we pass a copy of the pointer, not copy of value. +Şimdi sorabilirsiniz `x` in kendisini nasıl fonksiyona verebilirim diye. + +Burada pointer kullanmamız gerekiyor. Biliyoruz ki değişkenler bellekte tutulur ve bir adresleri vardır. Eğer değişkenin aslını değiştirmek istiyorsak onun bellek adresini kullanmalıyız. Böylelikle `add1` fonksiyonu `x` in adresini kullanarak onun değerini değiştirebilir. Parametre türünü `*int` olarak değiştiriyoruz ve değişkenin adresini `&x` ile fonksiyona veriyoruz. Fonksiyona değerin bir kopyasını değil de bir pointer verdiğimize dikkat edin. package main import "fmt" @@ -321,16 +321,16 @@ We need use pointers here. We know variables are stored in memory and they have fmt.Println("x+1 = ", x1) // should print "x+1 = 4" fmt.Println("x = ", x) // should print "x = 4" } - -Now we can change the value of `x` in the functions. Why do we use pointers? What are the advantages? -- Allows us to use more functions to operate on one variable. -- Low cost by passing memory addresses (8 bytes), copy is not an efficient way, both in terms of time and space, to pass variables. -- `string`, `slice` and `map` are reference types, so they use pointers when passing to functions by default. (Attention: If you need to change the length of `slice`, you have to pass pointers explicitly) +Şimdi `x` in asıl değerini değiştirebiliriz. Neden pointer kullanıyoruz? Avantajı nedir? + +- Bir değişken üzerinde çalışmak için birden fazla fonksiyon kullanabilmemize olanak sağlar. +- Adres (8 byte) verdiğimiz için maliyet azalır. Değerin kopyasını vermek maliyet ve zaman için verimli bir yöntem değildir. +- `string`, `slice`, `map` referans türlerdir. Yani fonksiyona verilirken standart olarak pointer olarak verilirler. (Dikkat: Eğer `slice` ın uzunluğunu değiştirmek istiyorsanız açıkça pointer olarak vermeniz gerekir.) ### defer -Go has a well designed keyword called `defer`. You can have many `defer` statements in one function; they will execute in reverse order when the program executes to the end of functions. In the case where the program opens some resource files, these files would have to be closed before the function can return with errors. Let's see some examples. +Go da iyi tasarlanmış `defer` (ertelemek) adlı bir terim vardır. Bir fonksiyonda birden fazla `defer` ifadesi bulunabilir, program çalıştığında sondan başa sırayla çalışacaklardır. Programın dosya açtığı durumlarda bu dosyaların hata vermeden önce kapatılması gerekir. Örneklere bakalım. func ReadWrite() bool { file.Open("file") @@ -348,8 +348,8 @@ Go has a well designed keyword called `defer`. You can have many `defer` stateme file.Close() return true } - -We saw some code being repeated several times. `defer` solves this problem very well. It doesn't only help you to write clean code but also makes your code more readable. + +Bazı kodların tekrar ettiğini görüyoruz. `defer` bu problemi çok iyi çözer. Daha temiz kod yazmanıza yardım etmekle kalmaz kodunuzu daha okunur yapar. func ReadWrite() bool { file.Open("file") @@ -362,20 +362,20 @@ We saw some code being repeated several times. `defer` solves this problem very } return true } - -If there are more than one `defer`s, they will execute by reverse order. The following example will print `4 3 2 1 0`. + +Eğer birden fazla `defer` varsa ters sırayla çalışırlar. Sıradaki örnek `4 3 2 1 0` sonucunu yazar. for i := 0; i < 5; i++ { defer fmt.Printf("%d ", i) } -### Functions as values and types +### Değer ve tür olarak fonksiyonlar -Functions are also variables in Go, we can use `type` to define them. Functions that have the same signature can be seen as the same type. +Go'da fonksiyonlar aynı zamanda değişken olabilirler. `type` onları kullanarak tanımlayabiliriz. Aynı imzaya sahip fonksiyonlar ayno tür olarak görülebilir. type typeName func(input1 inputType1 , input2 inputType2 [, ...]) (result1 resultType1 [, ...]) - -What's the advantage of this feature? The answer is that it allows us to pass functions as values. + +Bunun avantajı nedir? Cevap, fonksiyonları değer olarak verebilmemizi sağlamasıdır. package main import "fmt" @@ -416,6 +416,8 @@ What's the advantage of this feature? The answer is that it allows us to pass fu even := filter(slice, isEven) fmt.Println("Even elements of slice are: ", even) } + +Interface kullanılan durumlarda çok yararlıdır. Gördüğünüz gibi `testInt` It's very useful when we use interfaces. As you can see `testInt` is a variable that has a function as type and the returned values and arguments of `filter` are the same as those of `testInt`. Therefore, we can have complex logic in our programs, while maintaining flexibility in our code. From 76e7b5d2af061d5665611134b3d8455868d079b0 Mon Sep 17 00:00:00 2001 From: Bora Kaplan Date: Wed, 31 Aug 2016 02:19:32 +0300 Subject: [PATCH 4/4] Translated 02.3.md to Turkish Code blocks are not translated yet. --- tr/02.3.md | 70 +++++++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/tr/02.3.md b/tr/02.3.md index 3e654abe..e0dc8a1c 100644 --- a/tr/02.3.md +++ b/tr/02.3.md @@ -417,19 +417,17 @@ Bunun avantajı nedir? Cevap, fonksiyonları değer olarak verebilmemizi sağlam fmt.Println("Even elements of slice are: ", even) } -Interface kullanılan durumlarda çok yararlıdır. Gördüğünüz gibi `testInt` - -It's very useful when we use interfaces. As you can see `testInt` is a variable that has a function as type and the returned values and arguments of `filter` are the same as those of `testInt`. Therefore, we can have complex logic in our programs, while maintaining flexibility in our code. +Interface kullanılan durumlarda çok yararlıdır. Gördüğünüz gibi `testInt` fonksiyon türünde bir değişkendir ve `filter` ın döndürdüğü argümanlar ve değerler `testInt` ile aynıdır. Böylelikle programlarımızda karmaşık mantık yürütebilir ve esneklik kazanabiliriz. -### Panic and Recover +### Panic ve Recover -Go doesn't have `try-catch` structure like Java does. Instead of throwing exceptions, Go uses `panic` and `recover` to deal with errors. However, you shouldn't use `panic` very much, although it's powerful. +Go da Java gibi `try-catch` yapısı yoktur. Go exception fırlatmak yerine `panic` ve `recover` ile hatalarla ilgilenir. Etkili olmasına karşın `panic` çok fazla kullanılmamalıdır. -`Panic` is a built-in function to break the normal flow of programs and get into panic status. When a function `F` calls `panic`, `F` will not continue executing but its `defer` functions will continue to execute. Then `F` goes back to the break point which caused the panic status. The program will not terminate until all of these functions return with panic to the first level of that `goroutine`. `panic` can be produced by calling `panic` in the program, and some errors also cause `panic` like array access out of bounds errors. +`Panic` programın normal akışını durdurmak ve panik haline sokmak için kullanılır. `F` adında bir fonksiyon `panic` çağırdığında fonksiyon çalışmayı durdurur ve ertelenen `defer` fonksiyonları çalıştırılır. Sonra `F` panik halinin başladığı yere döner. Bütün fonksiyonlar `F` gibi başladığı yerdeki `goroutine` e dönmeden program sonlanmaz. `panic` programın içinde `panic` olarak çağırıldığında gerçekleşir. Ayrıca dizi sınırları dışına erişim hataları gibi bazı hatalar da `panic` sebebi olabilir. -`Recover` is a built-in function to recover `goroutine`s from panic status. Calling `recover` in `defer` functions is useful because normal functions will not be executed when the program is in the panic status. It catches `panic` values if the program is in the panic status, and it gets `nil` if the program is not in panic status. +`Recover` (kurtarmak) `goroutine` leri panik halinden kurtarmak için kullanılır. `defer` fonksiyonlarının içinde `recover` çağırmak yararlıdır çünkü panik halinde normal fonksiyonlar çalışmayı durdurur. Çağırıldığında varsa `panic` değerlerini yakalar yoksa `nil` yakalar. -The following example shows how to use `panic`. +Aşağıdaki örnekte `panic` nasıl kullanılır gösterilmiştir. var user = os.Getenv("USER") @@ -438,8 +436,8 @@ The following example shows how to use `panic`. panic("no value for $USER") } } - -The following example shows how to check `panic`. + +Bu örnek de `panic` kontrolü yapılmasını gösterir. func throwsPanic(f func()) (b bool) { defer func() { @@ -451,67 +449,69 @@ The following example shows how to check `panic`. return } -### `main` function and `init` function +### `main` ve `init` fonksiyonları -Go has two retentions which are called `main` and `init`, where `init` can be used in all packages and `main` can only be used in the `main` package. These two functions are not able to have arguments or return values. Even though we can write many `init` functions in one package, I strongly recommend writing only one `init` function for each package. +`init` fonksiyonu tüm paketlerde kullanılabilirken `main` fonksiyonu sadece `main` paketinde kullanılabilir. Bu iki fonksiyonun parametreleri yoktur ve değer döndürmezler. Bir paket içinde birden çok `init` yazılabilse de sadece bir tane yazılmasını kesinlikle tavsiye ederim. -Go programs will call `init()` and `main()` automatically, so you don't need to call them by yourself. For every package, the `init` function is optional, but `package main` has one and only one `main` function. +Go programları `init()` ve `main()` i otomatik çağırır. Her paket için `init` fonksiyonu isteğe bağlı iken `main` paketi için sadece bir tane `main` fonksiyonu kesinlikle bulunmak zorundadır. -Programs initialize and begin execution from the `main` package. If the `main` package imports other packages, they will be imported in the compile time. If one package is imported many times, it will be only compiled once. After importing packages, programs will initialize the constants and variables within the imported packages, then execute the `init` function if it exists, and so on. After all the other packages are initialized, programs will initialize constants and variables in the `main` package, then execute the `init` function inside the package if it exists. The following figure shows the process. +Programlar işleme `main` paketinden başlar. Eğer `main` başka paketler dahil (import) ediyorsa derleme sürecinde onlar da dahil edilir. Bir paket birden fazla kez dahil edildiyse bile sadece bir kere derlenir. Paketler dahil edildikten sonra program bu paketlerdeki değişkenleri ve sabitleri parafe eder ve sonra varsa `init` çalıştırılır ve böyle devam eder. Bütün paketler parafe edildikten sonra program `main` paketindeki değişkenleri ve sabitleri parafe eder ve varsa `init` çalıştırılır. Alttaki şekil bu süreci gösterir. ![](images/2.3.init.png?raw=true) -Figure 2.6 Flow of programs initialization in Go +Figure 2.6 Go da programların parafe edilmesinin akışı ### import -We use `import` very often in Go programs as follows. +Go programlarında `import` (dahil etmek) aşağıdaki gibi çok sık kullanılır import( "fmt" ) - -Then we use functions in that package as follows. + +Sonra dahil edilen bu paketteki fonksiyonlar aşağıdaki gibi kullanılır. fmt.Println("hello world") - -`fmt` is from Go standard library, it is located within $GOROOT/pkg. Go supports third-party packages in two ways. -1. Relative path +`fmt` Go standart kütüphanesinde bulunur. Bilgisayarda $GOROOT/pkg da bulunur. Go üçüncü şahış paketlerini iki şekilde destekler. + +1. Göreceli yol import "./model" // load package in the same directory, I don't recommend this way. -2. Absolute path +2. Kesin yol import "shorturl/model" // load package in path "$GOPATH/pkg/shorturl/model" - -There are some special operators when we import packages, and beginners are always confused by these operators. -1. Dot operator. - Sometime we see people use following way to import packages. +Paketler dahil edilirken kullanılan özel operatörler vardır ve bunlar genelde yeni başlayanların kafalarını kurcalar. + +1. Nokta operatörü + Bazen aşağıdaki gibi kullanıldığını görürüz. import( . "fmt" ) - The dot operator means you can omit the package name when you call functions inside of that package. Now `fmt.Printf("Hello world")` becomes to `Printf("Hello world")`. -2. Alias operation. - It changes the name of the package that we imported when we call functions that belong to that package. + Nokta operatörünün görevi, bir paketten fonksiyon çağırırken paketin adının yazılma gereksinimini kaldırmasıdır. Böylelikle `fmt.Printf("Hello world")` yerine `Printf("Hello world")` yazılır. + +2. Takma isim verme + Pakete takma isim vererek fonksiyon çağırırken kullanılan ad değiştirilir. import( f "fmt" ) - Now `fmt.Printf("Hello world")` becomes to `f.Printf("Hello world")`. -3. `_` operator. - This is the operator that is difficult to understand without someone explaining it to you. + Böylelikle `fmt.Printf("Hello world")` yerine `f.Printf("Hello world")` yazılır. + +3. `_` operatorü + Bunu anlamak zordur özellikle biri size açıklamadıysa. import ( "database/sql" _ "github.com/ziutek/mymysql/godrv" ) - The `_` operator actually means we just want to import that package and execute its `init` function, and we are not sure if want to use the functions belonging to that package. + Bu operatör dahil edilen paketin sadece `init` fonksiyonun çağrılıp çalıştırılması için kullanılır. Paketteki diğer fonksiyonları kullanacağınıza emin değilseniz kullanabilirsiniz. ## Links - [Directory](preface.md) -- Previous section: [Go foundation](02.2.md) -- Next section: [struct](02.4.md) +- Önceki bölüm: [Go foundation](02.2.md) +- Sonraki bölüm: [struct](02.4.md)