|
30 | 30 | " in the sense that the length of an array is part of its type\n", |
31 | 31 | " and must be determined at compile time.\n", |
32 | 32 | " \n", |
33 | | - "2. Array is a primitive (value) type in Golang.\n", |
34 | | - " When assigned to another variable \n", |
35 | | - " or passed as a parameter,\n", |
| 33 | + "2. When an array is assigned to another variable \n", |
| 34 | + " or passed to a function as a parameter,\n", |
36 | 35 | " it is copied!\n", |
37 | 36 | " For this reason, \n", |
38 | 37 | " array is not a good interface to use.\n", |
|
480 | 479 | "source": [ |
481 | 480 | "## [Slice](https://go.dev/ref/spec#Slice_types)\n", |
482 | 481 | "\n", |
483 | | - "Slice in Golang is similar to `Vec` in Rust." |
| 482 | + "A Slice in Golang is similar to a dynamic array (or vector) in other programming languages.\n", |
| 483 | + "However,\n", |
| 484 | + "due to Golang's unique design (lacking of class),\n", |
| 485 | + "a Slice behaves different and sometimes confusing to users coming from other programming languages.\n", |
| 486 | + "A Slice in Golang is implemented as a descriptor (struct) containing a data pointer, a length and a capacity. \n", |
| 487 | + "Due to this design,\n", |
| 488 | + "1. When you pass a Slice (value copy) to a function in Golang,\n", |
| 489 | + " the function can update existing values in the Slice\n", |
| 490 | + " (as the copied Slice in the function shares the same underlying data pointer as the original Slice).\n", |
| 491 | + "2. The built-in function `append` can be used to append values into a slice.\n", |
| 492 | + " Since `append` takes a Slice (instead of a pointer to a Slice) by value,\n", |
| 493 | + " it cannot update the original Slice descriptor (struct),\n", |
| 494 | + " so it has to return a new Slice descriptor.\n", |
| 495 | + " This sounds like append isn't appending in place\n", |
| 496 | + " which is a misunderstanding.\n", |
| 497 | + " - When there's no capacity left in the underlying array,\n", |
| 498 | + " append has to allocate a new chunk of memory and copies value over.\n", |
| 499 | + " Appending isn't in place in this case,\n", |
| 500 | + " but it's true in any programming language.\n", |
| 501 | + " - When there's capacity left in the udnerlying array,\n", |
| 502 | + " appending happens in place in the underlying array\n", |
| 503 | + " (as no new memory allocation is required).\n", |
| 504 | + " However,\n", |
| 505 | + " since a new slice descriptor is returned by `append`\n", |
| 506 | + " and the origial slice descriptor stays the same,\n", |
| 507 | + " the original slice descriptor is still a view of the old array window\n", |
| 508 | + " instead of the new updated array window.\n", |
| 509 | + " - Sometimes,\n", |
| 510 | + " you want to pass a slice to another function for appending values\n", |
| 511 | + " and want the change to be reflected outside the function.\n", |
| 512 | + " To achieve this,\n", |
| 513 | + " you can pass a pointor to the Slice descriptor.\n", |
| 514 | + " " |
484 | 515 | ] |
485 | 516 | }, |
486 | 517 | { |
|
666 | 697 | "source": [ |
667 | 698 | "## Appending to a Slice\n", |
668 | 699 | "\n", |
669 | | - "[Appending to a slice](https://go.dev/tour/moretypes/15)" |
| 700 | + "[Appending to a slice](https://go.dev/tour/moretypes/15)\n", |
| 701 | + "\n", |
| 702 | + "1. Appending to " |
670 | 703 | ] |
671 | 704 | }, |
672 | 705 | { |
|
815 | 848 | }, |
816 | 849 | { |
817 | 850 | "cell_type": "code", |
818 | | - "execution_count": 47, |
| 851 | + "execution_count": 1, |
819 | 852 | "metadata": {}, |
820 | 853 | "outputs": [ |
821 | 854 | { |
822 | 855 | "data": { |
823 | | - "text/plain": [ |
824 | | - "[78 89 45 56 14]" |
| 856 | + "text/html": [ |
| 857 | + "\n", |
| 858 | + "<style>\n", |
| 859 | + ".gonb-err-location {\n", |
| 860 | + "\tbackground: var(--jp-err-color2); \n", |
| 861 | + "\tborder-radius: 3px;\n", |
| 862 | + "\tborder-style: dotted;\n", |
| 863 | + "\tborder-width: 1px;\n", |
| 864 | + "\tborder-color: var(--jp-border-color2);\n", |
| 865 | + "}\n", |
| 866 | + ".gonb-err-location:hover {\n", |
| 867 | + "\tborder-width: 2px;\n", |
| 868 | + "\tborder-style: solid;\n", |
| 869 | + "\tborder-color: var(--jp-border-color2);\n", |
| 870 | + "}\n", |
| 871 | + ".gonb-err-context {\n", |
| 872 | + "\tdisplay: none;\n", |
| 873 | + "}\n", |
| 874 | + ".gonb-err-location:hover + .gonb-err-context {\n", |
| 875 | + "\tbackground: var(--jp-dialog-background); \n", |
| 876 | + "\tborder-radius: 3px;\n", |
| 877 | + "\tborder-style: solid;\n", |
| 878 | + "\tborder-width: 1px;\n", |
| 879 | + "\tborder-color: var(--jp-border-color2);\n", |
| 880 | + "\tdisplay: block;\n", |
| 881 | + "\twhite-space: pre;\n", |
| 882 | + "\tfont-family: monospace;\n", |
| 883 | + "}\n", |
| 884 | + ".gonb-err-line {\n", |
| 885 | + "\tborder-radius: 3px;\n", |
| 886 | + "\tborder-style: dotted;\n", |
| 887 | + "\tborder-width: 1px;\t\n", |
| 888 | + "\tborder-color: var(--jp-border-color2);\n", |
| 889 | + "\tbackground-color: var(--jp-rendermime-err-background);\n", |
| 890 | + "\tfont-weight: bold;\n", |
| 891 | + "}\n", |
| 892 | + ".gonb-cell-line-info {\n", |
| 893 | + "\tbackground: var(--jp-layout-color2);\n", |
| 894 | + "\tcolor: #999;\n", |
| 895 | + "\tmargin: 0.1em;\n", |
| 896 | + "\tborder: 1px solid var(--jp-border-color1);\n", |
| 897 | + "\tpadding-left: 0.2em;\n", |
| 898 | + "\tpadding-right: 0.2em;\n", |
| 899 | + "}\n", |
| 900 | + "</style>\n", |
| 901 | + "<div class=\"lm-Widget p-Widget lm-Panel p-Panel jp-OutputArea-child\">\n", |
| 902 | + "<div class=\"lm-Widget p-Widget jp-RenderedText jp-mod-trusted jp-OutputArea-output\" data-mime-type=\"application/vnd.jupyter.stderr\" style=\"font-family: monospace;\">\n", |
| 903 | + "\n", |
| 904 | + "<span class=\"gonb-cell-line-info\">Cell[1]: Line 1</span>\n", |
| 905 | + "<span class=\"gonb-err-location\">/tmp/gonb_e532465a/main.go:3:1: </span> expected declaration, found vec\n", |
| 906 | + "<div class=\"gonb-err-context\">\n", |
| 907 | + "package main\n", |
| 908 | + "\n", |
| 909 | + "<div class=\"gonb-err-line\">vec := []int{78, 89, 45, 56, 14}\n", |
| 910 | + "</div>vec\n", |
| 911 | + "\n", |
| 912 | + "\n", |
| 913 | + "</div>\n", |
| 914 | + "\n", |
| 915 | + "<br/>\n", |
| 916 | + "\n", |
| 917 | + "</div>\n" |
825 | 918 | ] |
826 | 919 | }, |
827 | | - "execution_count": 47, |
828 | 920 | "metadata": {}, |
829 | | - "output_type": "execute_result" |
| 921 | + "output_type": "display_data" |
| 922 | + }, |
| 923 | + { |
| 924 | + "ename": "ERROR", |
| 925 | + "evalue": "parsing go files in TempDir \"/tmp/gonb_e532465a\": /tmp/gonb_e532465a/main.go:3:1: expected declaration, found vec", |
| 926 | + "output_type": "error", |
| 927 | + "traceback": [ |
| 928 | + "parsing go files in TempDir \"/tmp/gonb_e532465a\": /tmp/gonb_e532465a/main.go:3:1: expected declaration, found vec" |
| 929 | + ] |
830 | 930 | } |
831 | 931 | ], |
832 | 932 | "source": [ |
|
855 | 955 | "vec" |
856 | 956 | ] |
857 | 957 | }, |
| 958 | + { |
| 959 | + "cell_type": "code", |
| 960 | + "execution_count": 9, |
| 961 | + "metadata": {}, |
| 962 | + "outputs": [ |
| 963 | + { |
| 964 | + "name": "stdout", |
| 965 | + "output_type": "stream", |
| 966 | + "text": [ |
| 967 | + "a len=0 cap=5 []\n", |
| 968 | + "b len=1 cap=5 [1]\n", |
| 969 | + "a len=0 cap=5 []\n", |
| 970 | + "a len=5 cap=5 [1 0 0 0 0]\n" |
| 971 | + ] |
| 972 | + } |
| 973 | + ], |
| 974 | + "source": [ |
| 975 | + "func printSlice(s string, x []int) {\n", |
| 976 | + "\tfmt.Printf(\"%s len=%d cap=%d %v\\n\",\n", |
| 977 | + "\t\ts, len(x), cap(x), x)\n", |
| 978 | + "}\n", |
| 979 | + "\n", |
| 980 | + "%%\n", |
| 981 | + "a := make([]int, 0, 5)\n", |
| 982 | + "printSlice(\"a\", a)\n", |
| 983 | + "b := append(a, 1)\n", |
| 984 | + "printSlice(\"b\", b)\n", |
| 985 | + "printSlice(\"a\", a)\n", |
| 986 | + "\n", |
| 987 | + "hdr := (*reflect.SliceHeader)(unsafe.Pointer(&a))\n", |
| 988 | + "data := *(*[5]int)(unsafe.Pointer(hdr.Data))\n", |
| 989 | + "printSlice(\"a\", data[:])" |
| 990 | + ] |
| 991 | + }, |
| 992 | + { |
| 993 | + "cell_type": "code", |
| 994 | + "execution_count": 11, |
| 995 | + "metadata": {}, |
| 996 | + "outputs": [ |
| 997 | + { |
| 998 | + "name": "stdout", |
| 999 | + "output_type": "stream", |
| 1000 | + "text": [ |
| 1001 | + "a len=0 cap=5 []\n", |
| 1002 | + "a len=1 cap=5 [1000]\n" |
| 1003 | + ] |
| 1004 | + } |
| 1005 | + ], |
| 1006 | + "source": [ |
| 1007 | + "func printSlice(s string, x []int) {\n", |
| 1008 | + "\tfmt.Printf(\"%s len=%d cap=%d %v\\n\",\n", |
| 1009 | + "\t\ts, len(x), cap(x), x)\n", |
| 1010 | + "}\n", |
| 1011 | + "\n", |
| 1012 | + "func myAppend(arr *[]int, val int) {\n", |
| 1013 | + " *arr = append(*arr, val)\n", |
| 1014 | + "}\n", |
| 1015 | + "\n", |
| 1016 | + "%%\n", |
| 1017 | + "a := make([]int, 0, 5)\n", |
| 1018 | + "printSlice(\"a\", a)\n", |
| 1019 | + "myAppend(&a, 1000)\n", |
| 1020 | + "printSlice(\"a\", a)" |
| 1021 | + ] |
| 1022 | + }, |
858 | 1023 | { |
859 | 1024 | "cell_type": "markdown", |
860 | 1025 | "metadata": {}, |
|
868 | 1033 | "metadata": { |
869 | 1034 | "file_extension": ".py", |
870 | 1035 | "kernelspec": { |
871 | | - "display_name": "Go", |
| 1036 | + "display_name": "Go (gonb)", |
872 | 1037 | "language": "go", |
873 | | - "name": "gophernotes" |
| 1038 | + "name": "gonb" |
874 | 1039 | }, |
875 | 1040 | "language_info": { |
876 | 1041 | "codemirror_mode": "", |
877 | 1042 | "file_extension": ".go", |
878 | | - "mimetype": "", |
| 1043 | + "mimetype": "text/x-go", |
879 | 1044 | "name": "go", |
880 | 1045 | "nbconvert_exporter": "", |
881 | 1046 | "pygments_lexer": "", |
882 | | - "version": "go1.18.3" |
| 1047 | + "version": "go1.25.4" |
883 | 1048 | }, |
884 | 1049 | "mimetype": "text/x-python", |
885 | 1050 | "name": "python", |
|
0 commit comments