Не рекомендуется использовать местный импорт таким образом. Вместо этого, связывайтесь с пакетом через вашу GOPATH, то есть github.com/your_github_username/your_project_dir/utilities
.
Предполагаемый каталог проекта:
$GOPATH/
|
src/
|
github.com/
|
your_github_username/
|
your_project_dir/
|utilities
main.go
проект: github.com/your_github_username/your_project_dir
пакет: github.com/your_github_username/your_project_dir/utilities
После этого стандарта ваш локальный пакет следует импортировать без проблем.
Это указатель на указатель, как и в C (на котором, несмотря на странный синтаксис квадратных скобок, основан Objective-C):
char c;
char *pc = &c;
char **ppc = &pc;
char ***pppc = &ppc;
и так далее, до бесконечности ( или пока у вас не закончится пространство для переменных).
Часто используется для передачи указателя на функцию, которая должна иметь возможность изменять сам указатель (например, перераспределение памяти для объекта переменного размера).
=====
В ответ на ваш запрос на образец, показывающий, как его использовать, вот код, который я написал для другого поста, который его иллюстрирует. Это функция appendStr ()
, которая управляет своими собственными выделениями (вам все равно нужно освободить финальную версию). Первоначально вы устанавливаете строку ( char *
) в NULL, а сама функция выделяет место по мере необходимости.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void appendToStr (int *sz, char **str, char *app) {
char *newstr;
int reqsz;
/* If no string yet, create it with a bit of space. */
if (*str == NULL) {
*sz = strlen (app) + 10;
if ((*str = malloc (*sz)) == NULL) {
*sz = 0;
return;
}
strcpy (*str, app);
return;
}
/* If not enough room in string, expand it. We could use realloc
but I've kept it as malloc/cpy/free to ensure the address
changes (for the program output). */
reqsz = strlen (*str) + strlen (app) + 1;
if (reqsz > *sz) {
*sz = reqsz + 10;
if ((newstr = malloc (*sz)) == NULL) {
free (*str);
*str = NULL;
*sz = 0;
return;
}
strcpy (newstr, *str);
free (*str);
*str = newstr;
}
/* Append the desired string to the (now) long-enough buffer. */
strcat (*str, app);
}
static void dump(int sz, char *x) {
if (x == NULL)
printf ("%8p [%2d] %3d [%s]\n", x, sz, 0, "");
else
printf ("%8p [%2d] %3d [%s]\n", x, sz, strlen (x), x);
}
static char *arr[] = {"Hello.", " My", " name", " is", " Pax",
" and"," I", " am", " old."};
int main (void) {
int i;
char *x = NULL;
int sz = 0;
printf (" Pointer Size Len Value\n");
printf (" ------- ---- --- -----\n");
dump (sz, x);
for (i = 0; i < sizeof (arr) / sizeof (arr[0]); i++) {
appendToStr (&sz, &x, arr[i]);
dump (sz, x);
}
}
Код выводит следующее. Вы можете увидеть, как изменяется указатель, когда в выделенной в данный момент памяти заканчивается место для расширенной строки (в комментариях):
Pointer Size Len Value
------- ---- --- -----
# NULL pointer here since we've not yet put anything in.
0x0 [ 0] 0 []
# The first time we put in something, we allocate space (+10 chars).
0x6701b8 [16] 6 [Hello.]
0x6701b8 [16] 9 [Hello. My]
0x6701b8 [16] 14 [Hello. My name]
# Adding " is" takes length to 17 so we need more space.
0x6701d0 [28] 17 [Hello. My name is]
0x6701d0 [28] 21 [Hello. My name is Pax]
0x6701d0 [28] 25 [Hello. My name is Pax and]
0x6701d0 [28] 27 [Hello. My name is Pax and I]
# Ditto for adding " am".
0x6701f0 [41] 30 [Hello. My name is Pax and I am]
0x6701f0 [41] 35 [Hello. My name is Pax and I am old.]
В этом случае вы передаете ** str
, поскольку вам нужно можно изменить значение * str
.
=====
Или следующее, которое выполняет сортировку по развернутому пузырьку (о, позор!) для строк, которые не находятся в массив. Он делает это путем прямого обмена адресами строк.
#include <stdio.h>
static void sort (char **s1, char **s2, char **s3, char **s4, char **s5) {
char *t;
if (strcmp (*s1, *s2) > 0) { t = *s1; *s1 = *s2; *s2 = t; }
if (strcmp (*s2, *s3) > 0) { t = *s2; *s2 = *s3; *s3 = t; }
if (strcmp (*s3, *s4) > 0) { t = *s3; *s3 = *s4; *s4 = t; }
if (strcmp (*s4, *s5) > 0) { t = *s4; *s4 = *s5; *s5 = t; }
if (strcmp (*s1, *s2) > 0) { t = *s1; *s1 = *s2; *s2 = t; }
if (strcmp (*s2, *s3) > 0) { t = *s2; *s2 = *s3; *s3 = t; }
if (strcmp (*s3, *s4) > 0) { t = *s3; *s3 = *s4; *s4 = t; }
if (strcmp (*s1, *s2) > 0) { t = *s1; *s1 = *s2; *s2 = t; }
if (strcmp (*s2, *s3) > 0) { t = *s2; *s2 = *s3; *s3 = t; }
if (strcmp (*s1, *s2) > 0) { t = *s1; *s1 = *s2; *s2 = t; }
}
int main (int argCount, char *argVar[]) {
char *a = "77";
char *b = "55";
char *c = "99";
char *d = "88";
char *e = "66";
printf ("Unsorted: [%s] [%s] [%s] [%s] [%s]\n", a, b, c, d, e);
sort (&a,&b,&c,&d,&e);
printf (" Sorted: [%s] [%s] [%s] [%s] [%s]\n", a, b, c, d, e);
return 0;
}
что дает:
Unsorted: [77] [55] [99] [88] [66]
Sorted: [55] [66] [77] [88] [99]
Не говоря уже о реализации сортировки, просто обратите внимание, что переменные передаются как char **
, так что они могут быть поменял местами легко. Любая настоящая сортировка, вероятно, будет воздействовать на настоящий массив данных, а не на отдельные переменные, но это не суть примера.
** str
, так как вам нужно иметь возможность изменить значение * str
.
=====
Или следующее, которое выполняет развернутую пузырьковая сортировка (о позор!) для строк, не входящих в массив. Он делает это путем прямого обмена адресами строк.
#include <stdio.h>
static void sort (char **s1, char **s2, char **s3, char **s4, char **s5) {
char *t;
if (strcmp (*s1, *s2) > 0) { t = *s1; *s1 = *s2; *s2 = t; }
if (strcmp (*s2, *s3) > 0) { t = *s2; *s2 = *s3; *s3 = t; }
if (strcmp (*s3, *s4) > 0) { t = *s3; *s3 = *s4; *s4 = t; }
if (strcmp (*s4, *s5) > 0) { t = *s4; *s4 = *s5; *s5 = t; }
if (strcmp (*s1, *s2) > 0) { t = *s1; *s1 = *s2; *s2 = t; }
if (strcmp (*s2, *s3) > 0) { t = *s2; *s2 = *s3; *s3 = t; }
if (strcmp (*s3, *s4) > 0) { t = *s3; *s3 = *s4; *s4 = t; }
if (strcmp (*s1, *s2) > 0) { t = *s1; *s1 = *s2; *s2 = t; }
if (strcmp (*s2, *s3) > 0) { t = *s2; *s2 = *s3; *s3 = t; }
if (strcmp (*s1, *s2) > 0) { t = *s1; *s1 = *s2; *s2 = t; }
}
int main (int argCount, char *argVar[]) {
char *a = "77";
char *b = "55";
char *c = "99";
char *d = "88";
char *e = "66";
printf ("Unsorted: [%s] [%s] [%s] [%s] [%s]\n", a, b, c, d, e);
sort (&a,&b,&c,&d,&e);
printf (" Sorted: [%s] [%s] [%s] [%s] [%s]\n", a, b, c, d, e);
return 0;
}
что дает:
Unsorted: [77] [55] [99] [88] [66]
Sorted: [55] [66] [77] [88] [99]
Не говоря уже о реализации сортировки, просто обратите внимание, что переменные передаются как char **
, так что они могут быть поменял местами легко. Любая реальная сортировка, вероятно, будет воздействовать на настоящий массив данных, а не на отдельные переменные, но это не суть примера.
** str
, так как вам нужно иметь возможность изменить значение * str
.
=====
Или следующее, которое выполняет развернутую пузырьковая сортировка (о позор!) для строк, не входящих в массив. Он делает это путем прямого обмена адресами строк.
#include <stdio.h>
static void sort (char **s1, char **s2, char **s3, char **s4, char **s5) {
char *t;
if (strcmp (*s1, *s2) > 0) { t = *s1; *s1 = *s2; *s2 = t; }
if (strcmp (*s2, *s3) > 0) { t = *s2; *s2 = *s3; *s3 = t; }
if (strcmp (*s3, *s4) > 0) { t = *s3; *s3 = *s4; *s4 = t; }
if (strcmp (*s4, *s5) > 0) { t = *s4; *s4 = *s5; *s5 = t; }
if (strcmp (*s1, *s2) > 0) { t = *s1; *s1 = *s2; *s2 = t; }
if (strcmp (*s2, *s3) > 0) { t = *s2; *s2 = *s3; *s3 = t; }
if (strcmp (*s3, *s4) > 0) { t = *s3; *s3 = *s4; *s4 = t; }
if (strcmp (*s1, *s2) > 0) { t = *s1; *s1 = *s2; *s2 = t; }
if (strcmp (*s2, *s3) > 0) { t = *s2; *s2 = *s3; *s3 = t; }
if (strcmp (*s1, *s2) > 0) { t = *s1; *s1 = *s2; *s2 = t; }
}
int main (int argCount, char *argVar[]) {
char *a = "77";
char *b = "55";
char *c = "99";
char *d = "88";
char *e = "66";
printf ("Unsorted: [%s] [%s] [%s] [%s] [%s]\n", a, b, c, d, e);
sort (&a,&b,&c,&d,&e);
printf (" Sorted: [%s] [%s] [%s] [%s] [%s]\n", a, b, c, d, e);
return 0;
}
что дает:
Unsorted: [77] [55] [99] [88] [66]
Sorted: [55] [66] [77] [88] [99]
Не говоря уже о реализации сортировки, просто обратите внимание, что переменные передаются как char **
, так что они могут быть поменял местами легко. Любая настоящая сортировка, вероятно, будет воздействовать на настоящий массив данных, а не на отдельные переменные, но это не суть примера.
Unsorted: [77] [55] [99] [88] [66]
Sorted: [55] [66] [77] [88] [99]
Не говоря уже о реализации сортировки, просто обратите внимание, что переменные передаются как char **
, чтобы их можно было легко поменять местами. Любая настоящая сортировка, вероятно, будет воздействовать на настоящий массив данных, а не на отдельные переменные, но это не суть примера.
Unsorted: [77] [55] [99] [88] [66]
Sorted: [55] [66] [77] [88] [99]
Не говоря уже о реализации сортировки, просто обратите внимание, что переменные передаются как char **
, чтобы их можно было легко поменять местами. Любая настоящая сортировка, вероятно, будет воздействовать на настоящий массив данных, а не на отдельные переменные, но это не суть примера.
В C указатели и массивы могут обрабатываться одинаково, то есть, например, char * - это строка (массив символов). Если вы хотите передать массив массивов (например, много строк) в функцию, вы можете использовать char **.